Compare commits
1 Commits
update-plu
...
3.84.0
Author | SHA1 | Date | |
---|---|---|---|
f467c43ccf |
@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Fetch the versions of WooCommerce from the WordPress API
|
||||
VERSIONS=$(curl -s https://api.wordpress.org/plugins/info/1.0/woocommerce.json | jq -r '.versions | keys_unsorted | .[]' | grep -v 'trunk')
|
||||
LATEST_VERSION=""
|
||||
|
||||
# Find the latest version
|
||||
for version in $VERSIONS; do
|
||||
LATEST_VERSION=$version
|
||||
done
|
||||
|
||||
# Check if the latest version is a beta/RC version
|
||||
if [[ $LATEST_VERSION != *'beta'* && $LATEST_VERSION != *'rc'* ]]; then
|
||||
echo "No WooCommerce beta/RC version found."
|
||||
echo "LATEST_BETA="
|
||||
else
|
||||
echo "Latest WooCommerce beta/RC version: $LATEST_VERSION"
|
||||
echo "LATEST_BETA=$LATEST_VERSION"
|
||||
fi
|
@ -1,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Fetch the WordPress releases RSS feed
|
||||
RSS_FEED=$(curl -s https://wordpress.org/news/category/releases/feed/)
|
||||
|
||||
# Extract the latest version from the feed and convert it to lowercase
|
||||
LAST_VERSION=$(echo "$RSS_FEED" | grep -o '<title>WordPress [^<]*</title>' | sed -E 's/<\/?title>//g' | head -n 1 | tr [:upper:] [:lower:])
|
||||
|
||||
# Check if a beta or RC version is found
|
||||
if [[ $LAST_VERSION == *'beta'* ]]; then
|
||||
# Extract titles containing beta versions from the feed
|
||||
VERSION_LINE=$(echo "$RSS_FEED" | grep -o '<code>wp core update [^<]*</code>' | sed -E 's/<\/?code>//g' | head -n 1 | grep 'beta')
|
||||
LATEST_BETA=$(echo "$VERSION_LINE" | sed -E 's/.*--version=([0-9\.]+-beta[0-9]+).*/\1/')
|
||||
|
||||
echo "Latest WordPress beta version: $LATEST_BETA"
|
||||
echo "LATEST_BETA=$LATEST_BETA"
|
||||
|
||||
elif [[ $LAST_VERSION == *'release candidate'* ]]; then
|
||||
# Extract titles containing RC versions from the feed
|
||||
VERSION_LINE=$(echo "$RSS_FEED" | grep -o '<code>wp core update [^<]*</code>' | sed -E 's/<\/?code>//g' | head -n 1 | grep 'RC')
|
||||
LATEST_BETA=$(echo "$VERSION_LINE" | sed -E 's/.*--version=([0-9\.]+-RC[0-9]+).*/\1/')
|
||||
|
||||
echo "Latest WordPress RC version: $LATEST_BETA"
|
||||
echo "LATEST_BETA=$LATEST_BETA"
|
||||
else
|
||||
echo "No WordPress beta/RC version found."
|
||||
echo "LATEST_BETA="
|
||||
fi
|
File diff suppressed because it is too large
Load Diff
@ -6,3 +6,4 @@ sendmail_path = /usr/local/bin/fake-sendmail.php
|
||||
; Defines the default timezone used by the date functions
|
||||
; http://php.net/date.timezone
|
||||
date.timezone = UTC
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
import * as fs from 'fs/promises';
|
||||
import * as os from 'os';
|
||||
|
||||
// Get logical CPU count for a container on CircleCI. Adapted from:
|
||||
// https://circleci.canny.io/cloud-feature-requests/p/have-nproc-accurately-reporter-number-of-cpus-available-to-container
|
||||
|
||||
async function cgroupCpuCount() {
|
||||
const quotaS = await fs.readFile('/sys/fs/cgroup/cpu/cpu.cfs_quota_us');
|
||||
const periodS = await fs.readFile('/sys/fs/cgroup/cpu/cpu.cfs_period_us');
|
||||
const quota = parseInt(quotaS);
|
||||
const period = parseInt(periodS);
|
||||
return quota / period;
|
||||
}
|
||||
|
||||
async function cpuCount() {
|
||||
try {
|
||||
return await cgroupCpuCount();
|
||||
} catch {
|
||||
return os.cpus().length;
|
||||
}
|
||||
}
|
||||
|
||||
cpuCount().then(console.log);
|
@ -12,7 +12,7 @@ function setup {
|
||||
sudo cp "$script_dir/fake-sendmail.php" /usr/local/bin/
|
||||
|
||||
# configure Apache
|
||||
sudo cp "$script_dir/mailpoet_php.ini" /etc/php.d/
|
||||
sudo cp "$script_dir/mailpoet_php.ini" /usr/local/etc/php/conf.d/
|
||||
sudo cp "$script_dir/apache/mailpoet.loc.conf" /etc/apache2/sites-available
|
||||
sudo a2dissite 000-default.conf
|
||||
sudo a2ensite mailpoet.loc
|
||||
@ -29,12 +29,14 @@ function setup {
|
||||
wp core download $wp_cli_wordpress_path $wp_cli_allow_root --version=${2:-latest}
|
||||
|
||||
# Generate `wp-config.php` file with debugging enabled
|
||||
wp config create --dbname=wordpress --dbuser=root --dbhost=127.0.0.1 --dbprefix='mp_' $wp_cli_wordpress_path $wp_cli_allow_root
|
||||
wp config set WP_DEBUG true --raw $wp_cli_wordpress_path $wp_cli_allow_root
|
||||
echo "define(\"WP_DEBUG\", true);" | wp core config --dbname=wordpress --dbuser=root --dbhost=127.0.0.1 --extra-php $wp_cli_wordpress_path $wp_cli_allow_root
|
||||
|
||||
# Disable WP Cron so that it doesn't interfere with tests
|
||||
wp config set DISABLE_WP_CRON true --raw $wp_cli_wordpress_path $wp_cli_allow_root
|
||||
|
||||
# Change default table prefix
|
||||
sed -i "s/\$table_prefix = 'wp_';/\$table_prefix = 'mp_';/" "$root_dir/wordpress/wp-config.php"
|
||||
|
||||
# Install WordPress
|
||||
if [[ $version == "php7_multisite" ]]; then
|
||||
# Configure multisite environment
|
||||
@ -70,9 +72,4 @@ function setup {
|
||||
# Activate MailPoet Premium
|
||||
wp plugin activate mailpoet-premium --path="$root_dir/wordpress"
|
||||
fi
|
||||
|
||||
# Fix WP formatting file for compatibility with PHP8.1
|
||||
sed -i "s|if ( strlen( \$email ) < 6 ) {|if ( strlen( (string) \$email ) < 6 ) {|" ../wordpress/wp-includes/formatting.php
|
||||
sed -i "s|return rtrim( \$string, '/\\\\\\\\' );|return rtrim( (string) \$string, '/\\\\\\\\' );|" ../wordpress/wp-includes/formatting.php
|
||||
sed -i "s|return \$wp_hasher->HashPassword( trim( \$password ) );|return \$wp_hasher->HashPassword( trim( (string) \$password ) );|" ../wordpress/wp-includes/pluggable.php
|
||||
}
|
||||
|
@ -7,59 +7,3 @@ insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
ij_smart_tabs = false
|
||||
max_line_length = off
|
||||
|
||||
[packages/php/email-editor/**]
|
||||
indent_style = tab
|
||||
|
||||
[packages/js/email-editor/**.{js,jsx,ts,tsx,scss}]
|
||||
indent_style = tab
|
||||
|
||||
[*.php]
|
||||
ij_php_align_key_value_pairs = false
|
||||
ij_php_align_multiline_chained_methods = false
|
||||
ij_php_align_assignments = false
|
||||
ij_php_align_class_constants = false
|
||||
ij_php_align_multiline_parameters = false
|
||||
ij_php_align_multiline_ternary_operation = false
|
||||
ij_php_align_inline_comments = false
|
||||
ij_php_align_multiline_for = true
|
||||
ij_php_align_named_arguments = false
|
||||
ij_php_align_multiline_array_initializer_expression = false
|
||||
ij_php_align_phpdoc_comments = false
|
||||
ij_php_blank_lines_after_class_header = 0
|
||||
ij_php_blank_lines_around_class = 1
|
||||
ij_php_blank_lines_before_class_end = 0
|
||||
ij_php_blank_lines_around_method = 1
|
||||
ij_php_blank_lines_after_opening_tag = 0
|
||||
ij_php_keep_indents_on_empty_lines = false
|
||||
ij_php_keep_blank_lines_after_lbrace = 0
|
||||
ij_php_keep_blank_lines_before_right_brace = 0
|
||||
ij_php_keep_blank_lines_in_declarations = 1
|
||||
ij_php_spaces_around_arrow = false
|
||||
ij_php_space_after_type_cast = false
|
||||
ij_php_blank_lines_after_function = 1
|
||||
ij_any_space_after_colon = true
|
||||
ij_any_space_before_comma = false
|
||||
ij_any_space_after_comma = true
|
||||
ij_php_space_before_catch_left_brace = true
|
||||
ij_php_space_before_if_left_brace = true
|
||||
ij_php_space_before_if_parentheses = true
|
||||
ij_php_space_after_quest = true
|
||||
ij_php_space_after_unary_not = false
|
||||
ij_php_space_before_quest = true
|
||||
ij_php_anonymous_brace_style = end_of_line
|
||||
ij_php_space_before_method_parentheses = false
|
||||
ij_php_space_before_method_call_parentheses = false
|
||||
ij_php_spaces_around_assignment_in_declare = true
|
||||
ij_php_method_parameters_new_line_after_left_paren = true
|
||||
ij_php_method_brace_style = end_of_line
|
||||
ij_php_blank_lines_before_method_body = 0
|
||||
ij_php_space_before_method_left_brace = true
|
||||
ij_php_space_after_for_semicolon = true
|
||||
ij_php_space_after_colon_in_return_type = true
|
||||
ij_php_space_before_else_keyword = true
|
||||
ij_php_for_statement_new_line_after_left_paren = true
|
||||
ij_php_class_brace_style = end_of_line
|
||||
ij_php_comma_after_last_array_element = true
|
||||
|
@ -37,17 +37,3 @@ e66c76133ec3ef667e382203426d91a4b4aa5174
|
||||
# Updating rule name in php:cs ignore comments
|
||||
65b834a9fff72b1ec5fc81ac383ebb27321da9dc
|
||||
|
||||
# Prettier autoformatting
|
||||
ab27eaee2df740c0add4331a7f8c115a87ecfa2b
|
||||
|
||||
# Move email editor to JS packages folder
|
||||
912282f57ccc839491ff951ec5cf7aa10c14f429
|
||||
|
||||
# Switch email editor js packages to WP coding style
|
||||
b2fb96f8793b63db629d5237010d87332330c51e
|
||||
|
||||
# Email editor Prettier autoformatting
|
||||
8c604453b1d82e3a2c731241e1c96ea8b32ec716
|
||||
|
||||
# Move email editor components out of the engine folder
|
||||
1c3ea9cd0a5fc8848a64d840e2fa16a6c7d8c1fe
|
||||
|
3
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@ -4,6 +4,7 @@ about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
@ -11,7 +12,6 @@ A clear and concise description of what the bug is.
|
||||
|
||||
**To reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to ...
|
||||
2. Click on ...
|
||||
3. Scroll down to ...
|
||||
@ -26,7 +26,6 @@ A clear and concise description of what you expected to happen.
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Versions (please complete the following information):**
|
||||
|
||||
- WordPress version: [e.g: 5.3.2]
|
||||
- PHP version: [e.g: 7.4.2]
|
||||
- MailPoet version: [e.g: 3.46.13]
|
||||
|
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
1
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -4,6 +4,7 @@ about: https://feedback.mailpoet.com/
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please use https://feedback.mailpoet.com/ for feature requests.
|
||||
|
22
.github/SECURITY.md
vendored
22
.github/SECURITY.md
vendored
@ -4,7 +4,7 @@ Full details of the Automattic Security Policy can be found on [automattic.com/s
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Generally, _only the latest version of MailPoet has continued support_. If a critical vulnerability is found in the current version of MailPoet, we may opt to backport any patches to previous versions.
|
||||
Generally, *only the latest version of MailPoet has continued support*. If a critical vulnerability is found in the current version of MailPoet, we may opt to backport any patches to previous versions.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
@ -14,9 +14,9 @@ Generally, _only the latest version of MailPoet has continued support_. If a cri
|
||||
|
||||
Our most critical targets are:
|
||||
|
||||
- MailPoet plugin (this repository)
|
||||
- MailPoet Premium
|
||||
- mailpoet.com -- the primary site, and all of it subdomains, e.g. [account.mailpoet.com](https://account.mailpoet.com/)
|
||||
* MailPoet plugin (this repository)
|
||||
* MailPoet Premium
|
||||
* mailpoet.com -- the primary site, and all of it subdomains, e.g. [account.mailpoet.com](https://account.mailpoet.com/)
|
||||
|
||||
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
|
||||
|
||||
@ -26,12 +26,12 @@ _Please note that the **WordPress software is a separate entity** from Automatti
|
||||
|
||||
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
|
||||
|
||||
- Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
|
||||
- Pen-testing Production:
|
||||
- Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
|
||||
- If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
|
||||
- **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
|
||||
- To be eligible for a bounty, please follow all of these guidelines.
|
||||
- Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
|
||||
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
|
||||
* Pen-testing Production:
|
||||
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
|
||||
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
|
||||
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
|
||||
* To be eligible for a bounty, please follow all of these guidelines.
|
||||
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
|
||||
|
||||
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.
|
||||
|
29
.github/pull_request_template.md
vendored
29
.github/pull_request_template.md
vendored
@ -1,29 +0,0 @@
|
||||
## Description
|
||||
|
||||
_N/A_
|
||||
|
||||
## Code review notes
|
||||
|
||||
_N/A_
|
||||
|
||||
## QA notes
|
||||
|
||||
_N/A_
|
||||
|
||||
## Linked PRs
|
||||
|
||||
_N/A_
|
||||
|
||||
## Linked tickets
|
||||
|
||||
_N/A_
|
||||
|
||||
## After-merge notes
|
||||
|
||||
_N/A_
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] I followed [best practices](https://codex.wordpress.org/I18n_for_WordPress_Developers) for translations
|
||||
- [ ] I added sufficient test coverage
|
||||
- [ ] I embraced TypeScript by either creating new files in TypeScript or converting existing JavaScript files when making changes
|
72
.github/workflows/codeql-analysis.yml
vendored
72
.github/workflows/codeql-analysis.yml
vendored
@ -3,14 +3,14 @@
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
name: 'CodeQL'
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [trunk]
|
||||
branches: [master]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [trunk]
|
||||
branches: [master]
|
||||
schedule:
|
||||
- cron: '0 17 * * 4'
|
||||
|
||||
@ -29,43 +29,43 @@ jobs:
|
||||
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
212
.github/workflows/email-editor-package.yml
vendored
212
.github/workflows/email-editor-package.yml
vendored
@ -1,212 +0,0 @@
|
||||
name: Email Editor Package Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ['7.4', '8.2']
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Composer vendor dependencies for MailPoet
|
||||
id: composer-mailpoet-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: mailpoet/vendor
|
||||
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('mailpoet/composer.lock') }}-${{ hashFiles('mailpoet/composer.json') }}
|
||||
|
||||
- name: Cache Composer vendor-prefixed dependencies for MailPoet
|
||||
id: vendor-prefixed-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: mailpoet/vendor-prefixed
|
||||
key: ${{ runner.os }}-vendor-prefixed-${{ matrix.php-version }}-${{ hashFiles('mailpoet/prefixer/composer.lock') }}-${{ hashFiles('mailpoet/prefixer/composer.json') }}
|
||||
|
||||
- name: Cache Composer vendor for test environment
|
||||
id: composer-tests-env-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: tests_env/vendor
|
||||
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('tests_env/composer.lock') }}-${{ hashFiles('tests_env/composer.json') }}
|
||||
|
||||
- name: Cache Composer dependencies for Email Editor
|
||||
id: composer-email-editor-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: packages/php/email-editor/vendor
|
||||
key: ${{ runner.os }}-composer-email-editor-${{ matrix.php-version }}-${{ hashFiles('packages/php/email-editor/composer.lock') }}-${{ hashFiles('packages/php/email-editor/composer.json') }}
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: gd
|
||||
|
||||
- name: Install tools
|
||||
run: |
|
||||
COMPOSER_DEV_MODE=1 php tools/install.php
|
||||
touch .env
|
||||
working-directory: mailpoet
|
||||
|
||||
# Install Test Environment dependencies only if the cache was not hit
|
||||
- name: Install test environment dependencies
|
||||
if: steps.composer-tests-env-cache.outputs.cache-hit != 'true'
|
||||
run: ../mailpoet/tools/vendor/composer.phar install
|
||||
working-directory: tests_env
|
||||
|
||||
# Install MailPoet dependencies only if the cache was not hit
|
||||
- name: Install mailpoet dependencies
|
||||
if: |
|
||||
steps.composer-mailpoet-cache.outputs.cache-hit != 'true' || steps.vendor-prefixed-cache.outputs.cache-hit != 'true'
|
||||
run: ./tools/vendor/composer.phar install
|
||||
working-directory: mailpoet
|
||||
|
||||
# Install Email Editor dependencies only if the cache was not hit
|
||||
- name: Install email-editor dependencies
|
||||
if: steps.composer-email-editor-cache.outputs.cache-hit != 'true'
|
||||
run: ../../../mailpoet/tools/vendor/composer.phar install
|
||||
working-directory: packages/php/email-editor
|
||||
|
||||
# Dump Email Editor autoload
|
||||
# This is needed to refresh classmap autoload when the composer cache is hit
|
||||
- name: Dump email-editor autoload
|
||||
run: ../../../mailpoet/tools/vendor/composer.phar dump-autoload
|
||||
working-directory: packages/php/email-editor
|
||||
|
||||
# Dump MailPoet autoload
|
||||
# This is needed to refresh classmap autoload when the composer cache is hit
|
||||
- name: Dump MailPoet autoload
|
||||
run: ./tools/vendor/composer.phar dump-autoload
|
||||
working-directory: mailpoet
|
||||
|
||||
# Run Email Editor unit tests
|
||||
- name: Run email-editor package unit tests
|
||||
run: ../../../tests_env/vendor/bin/codecept build && ../../../mailpoet/tools/vendor/composer.phar unit-test
|
||||
working-directory: packages/php/email-editor
|
||||
|
||||
- name: Run email-editor package integration tests
|
||||
run: ../../../mailpoet/tools/vendor/composer.phar integration-test
|
||||
working-directory: packages/php/email-editor
|
||||
|
||||
code-style:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.2'
|
||||
|
||||
- name: Install tools
|
||||
run: |
|
||||
COMPOSER_DEV_MODE=1 php tools/install.php
|
||||
touch .env
|
||||
working-directory: mailpoet
|
||||
|
||||
- name: Install composer dependencies
|
||||
run: ../../tools/vendor/composer.phar install
|
||||
working-directory: mailpoet/tasks/code_sniffer
|
||||
|
||||
- name: Run code style check
|
||||
run: ../../../mailpoet/tools/vendor/composer.phar code-style
|
||||
working-directory: packages/php/email-editor
|
||||
|
||||
phpstan-static-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ['7.4', '8.2']
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Composer vendor dependencies for MailPoet
|
||||
id: composer-mailpoet-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: mailpoet/vendor
|
||||
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('mailpoet/composer.lock') }}-${{ hashFiles('mailpoet/composer.json') }}
|
||||
|
||||
- name: Cache Composer vendor-prefixed dependencies for MailPoet
|
||||
id: vendor-prefixed-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: mailpoet/vendor-prefixed
|
||||
key: ${{ runner.os }}-vendor-prefixed-${{ matrix.php-version }}-${{ hashFiles('mailpoet/prefixer/composer.lock') }}-${{ hashFiles('mailpoet/prefixer/composer.json') }}
|
||||
|
||||
- name: Cache Composer vendor for test environment
|
||||
id: composer-tests-env-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: tests_env/vendor
|
||||
key: ${{ runner.os }}-composer-mailpoet-${{ matrix.php-version }}-${{ hashFiles('tests_env/composer.lock') }}-${{ hashFiles('tests_env/composer.json') }}
|
||||
|
||||
- name: Cache Composer dependencies for Email Editor
|
||||
id: composer-email-editor-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: packages/php/email-editor/vendor
|
||||
key: ${{ runner.os }}-composer-email-editor-${{ matrix.php-version }}-${{ hashFiles('packages/php/email-editor/composer.lock') }}-${{ hashFiles('packages/php/email-editor/composer.json') }}
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
extensions: gd
|
||||
|
||||
- name: Install tools
|
||||
run: |
|
||||
COMPOSER_DEV_MODE=1 php tools/install.php
|
||||
touch .env
|
||||
working-directory: mailpoet
|
||||
|
||||
# Install Test Environment dependencies only if the cache was not hit
|
||||
- name: Install test environment dependencies
|
||||
if: steps.composer-tests-env-cache.outputs.cache-hit != 'true'
|
||||
run: ../mailpoet/tools/vendor/composer.phar install
|
||||
working-directory: tests_env
|
||||
|
||||
# Install MailPoet dependencies only if the cache was not hit
|
||||
- name: Install mailpoet dependencies
|
||||
if: |
|
||||
steps.composer-mailpoet-cache.outputs.cache-hit != 'true' || steps.vendor-prefixed-cache.outputs.cache-hit != 'true'
|
||||
run: ./tools/vendor/composer.phar install
|
||||
working-directory: mailpoet
|
||||
|
||||
# Install Email Editor dependencies only if the cache was not hit
|
||||
- name: Install email-editor dependencies
|
||||
if: steps.composer-email-editor-cache.outputs.cache-hit != 'true'
|
||||
run: ../../../mailpoet/tools/vendor/composer.phar install
|
||||
working-directory: packages/php/email-editor
|
||||
|
||||
- name: Install composer dependencies
|
||||
run: ../../tools/vendor/composer.phar install
|
||||
working-directory: mailpoet/tasks/phpstan
|
||||
|
||||
# Dump Email Editor autoload
|
||||
# This is needed to refresh classmap autoload when the composer cache is hit
|
||||
- name: Dump email-editor autoload
|
||||
run: ../../../mailpoet/tools/vendor/composer.phar dump-autoload
|
||||
working-directory: packages/php/email-editor
|
||||
|
||||
# Dump MailPoet autoload
|
||||
# This is needed to refresh classmap autoload when the composer cache is hit
|
||||
- name: Dump MailPoet autoload
|
||||
run: ./tools/vendor/composer.phar dump-autoload
|
||||
working-directory: mailpoet
|
||||
|
||||
- name: Run code phpstan
|
||||
run: ../../../mailpoet/tools/vendor/composer.phar phpstan -- --php-version=${{ matrix.php-version == '7.4' && '70400' || '80200' }}
|
||||
working-directory: packages/php/email-editor
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
$repository = 'woocommerce/automatewoo';
|
||||
$downloadCommand = 'download:automate-woo-zip';
|
||||
$configParameterName = 'automate_woo_version';
|
||||
$versionsFilenameSuffix = 'automate_woo_version.txt';
|
||||
|
||||
replacePrivatePluginVersion($repository, $downloadCommand, $configParameterName, $versionsFilenameSuffix);
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
$repository = 'woocommerce/woocommerce-memberships';
|
||||
$downloadCommand = 'download:woo-commerce-memberships-zip';
|
||||
$configParameterName = 'woo_memberships_version';
|
||||
$versionsFilenameSuffix = 'woocommerce_memberships_version.txt';
|
||||
|
||||
replacePrivatePluginVersion($repository, $downloadCommand, $configParameterName, $versionsFilenameSuffix);
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
$repository = 'woocommerce/woocommerce-subscriptions';
|
||||
$downloadCommand = 'download:woo-commerce-subscriptions-zip';
|
||||
$configParameterName = 'woo_subscriptions_version';
|
||||
$versionsFilenameSuffix = 'woocommerce_subscriptions_version.txt';
|
||||
|
||||
replacePrivatePluginVersion($repository, $downloadCommand, $configParameterName, $versionsFilenameSuffix);
|
@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
$downloadCommand = 'download:woo-commerce-zip';
|
||||
$configParameterName = 'woo_core_version';
|
||||
$versionsFilenameSuffix = 'woocommerce_version.txt';
|
||||
|
||||
/**
|
||||
* We get the official WooCommerce versions from the WordPress API.
|
||||
*/
|
||||
function getWooCommerceVersions(): array {
|
||||
$url = "https://api.wordpress.org/plugins/info/1.0/woocommerce.json";
|
||||
$response = file_get_contents($url);
|
||||
$data = json_decode($response, true);
|
||||
|
||||
if (!isset($data['versions'])) {
|
||||
die("Failed to fetch WooCommerce versions.");
|
||||
}
|
||||
|
||||
return array_keys($data['versions']);
|
||||
}
|
||||
|
||||
$allVersions = getWooCommerceVersions();
|
||||
$stableVersions = filterStableVersions($allVersions);
|
||||
[$latestVersion, $previousVersion] = getLatestAndPreviousMinorMajorVersions($stableVersions);
|
||||
|
||||
echo "Latest WooCommerce version: $latestVersion\n";
|
||||
echo "Previous WooCommerce version: $previousVersion\n";
|
||||
|
||||
if ($latestVersion) {
|
||||
echo "Replacing the latest version in the config file...\n";
|
||||
replaceLatestVersion($latestVersion, $downloadCommand);
|
||||
} else {
|
||||
echo "No latest version found.\n";
|
||||
}
|
||||
|
||||
if ($previousVersion) {
|
||||
echo "Replacing the previous version in the config file...\n";
|
||||
replacePreviousVersion($previousVersion, $configParameterName);
|
||||
} else {
|
||||
echo "No previous version found.\n";
|
||||
}
|
||||
|
||||
saveVersionsToFiles($latestVersion, $previousVersion, $versionsFilenameSuffix);
|
@ -1,123 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
/**
|
||||
* We try to get the current available official Docker images for WordPress.
|
||||
*/
|
||||
function getWordpressVersions(int $page = 1, int $pageSize = 100): array {
|
||||
$url = "https://registry.hub.docker.com/v2/repositories/library/wordpress/tags?page_size={$pageSize}&page={$page}";
|
||||
$response = file_get_contents($url);
|
||||
$data = json_decode($response, true);
|
||||
return array_column($data['results'], 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* We prefer the latest patch versions of WordPress with specified PHP versions.
|
||||
* For example: 6.5.4-php8.3
|
||||
*/
|
||||
function filterVersions(array $versions): array {
|
||||
return array_filter($versions, fn($version) => preg_match('/^\d+\.\d+\.\d+-php\d+\.\d+$/', $version));
|
||||
}
|
||||
|
||||
/**
|
||||
* We sort the versions by WordPress version and PHP version.
|
||||
* The expected output is:
|
||||
* - 6.5.4-php8.3
|
||||
* - 6.5.4-php8.2
|
||||
* - 6.5.3-php8.3
|
||||
* - 6.5.3-php8.2
|
||||
*/
|
||||
function sortVersions(&$versions) {
|
||||
usort($versions, function($a, $b) {
|
||||
[$wpA, $phpA] = explode('-php', $a);
|
||||
[$wpB, $phpB] = explode('-php', $b);
|
||||
|
||||
$wpCompare = version_compare($wpB, $wpA);
|
||||
return $wpCompare !== 0 ? $wpCompare : version_compare($phpB, $phpA);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function group docker tags by the WordPress version and returns the latest with the higher PHP version
|
||||
* abd the previous with the lower PHP version.
|
||||
*/
|
||||
function getLatestAndPreviousVersions(array $sortedVersions): array {
|
||||
$uniqueVersions = [];
|
||||
foreach ($sortedVersions as $version) {
|
||||
[$wpVersion] = explode('-php', $version);
|
||||
$majorMinorVersion = preg_replace('/\.\d+$/', '', $wpVersion);
|
||||
$uniqueVersions[$majorMinorVersion][] = $version;
|
||||
}
|
||||
|
||||
krsort($uniqueVersions);
|
||||
$latestVersionGroup = reset($uniqueVersions);
|
||||
$previousVersionGroup = next($uniqueVersions);
|
||||
|
||||
$latestVersion = $latestVersionGroup === false ? null : reset($latestVersionGroup);
|
||||
$previousVersion = $previousVersionGroup === false ? null : end($previousVersionGroup);
|
||||
|
||||
return [$latestVersion, $previousVersion];
|
||||
}
|
||||
|
||||
/**
|
||||
* We specify the latest WordPress version only in the docker-compose file for the tests.
|
||||
*/
|
||||
function replaceLatestWordPressVersion(string $latestVersion): void {
|
||||
replaceVersionInFile(
|
||||
__DIR__ . './../../../tests_env/docker/docker-compose.yml',
|
||||
'/(wordpress:\${WORDPRESS_IMAGE_VERSION:-\s*)\d+\.\d+\.?\d*-php\d+\.\d+(})/',
|
||||
'${1}' . $latestVersion . '${2}'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* We use the previous WordPress version only in the CircleCI config file.
|
||||
*/
|
||||
function replacePreviousWordPressVersion(string $previousVersion): void {
|
||||
replaceVersionInFile(
|
||||
__DIR__ . './../../../.circleci/config.yml',
|
||||
'/(wordpress_version: )\d+\.\d+\.?\d*/',
|
||||
'${1}' . $previousVersion
|
||||
);
|
||||
}
|
||||
|
||||
$allVersions = [];
|
||||
$page = 1;
|
||||
$maxPages = 8;
|
||||
$latestVersion = null;
|
||||
$previousVersion = null;
|
||||
|
||||
echo "Fetching WordPress versions...\n";
|
||||
|
||||
// We fetch the versions until we find the latest and previous versions. But there is a limit of 4 pages.
|
||||
while (($latestVersion === null || $previousVersion === null) && $page <= $maxPages) {
|
||||
echo "Fetching page $page...\n";
|
||||
$versions = getWordpressVersions($page);
|
||||
$allVersions = array_merge($allVersions, $versions);
|
||||
$allVersions = filterVersions($allVersions);
|
||||
sortVersions($allVersions);
|
||||
[$latestVersion, $previousVersion] = getLatestAndPreviousVersions($allVersions);
|
||||
$page++;
|
||||
}
|
||||
|
||||
echo "Latest version: $latestVersion\n";
|
||||
echo "Previous version: $previousVersion\n";
|
||||
|
||||
if ($latestVersion) {
|
||||
echo "Replacing the latest version in the docker file...\n";
|
||||
replaceLatestWordPressVersion($latestVersion);
|
||||
} else {
|
||||
echo "No latest version found.\n";
|
||||
}
|
||||
|
||||
if ($previousVersion) {
|
||||
echo "Replacing the previous version in the config file...\n";
|
||||
// We install previous WordPress version via CLI so we need a version without PHP in the name.
|
||||
$previousVersion = preg_replace('/-php\d+\.\d+$/', '', $previousVersion);
|
||||
replacePreviousWordPressVersion($previousVersion);
|
||||
} else {
|
||||
echo "No previous version found.\n";
|
||||
}
|
||||
|
||||
saveVersionsToFiles($latestVersion, $previousVersion, 'wordpress_version.txt');
|
156
.github/workflows/scripts/helpers.php
vendored
156
.github/workflows/scripts/helpers.php
vendored
@ -1,156 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Function replacing versions in a file by the regex pattern.
|
||||
*/
|
||||
function replaceVersionInFile(string $filePath, string $pattern, string $replacement): void {
|
||||
$content = file_get_contents($filePath);
|
||||
|
||||
if ($content === false) {
|
||||
die("Failed to read the file at $filePath.");
|
||||
}
|
||||
|
||||
$updatedContent = preg_replace($pattern, $replacement, $content);
|
||||
|
||||
if ($updatedContent === null || $updatedContent === $content) {
|
||||
echo "Nothing to update in $filePath\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_put_contents($filePath, $updatedContent) === false) {
|
||||
die("Failed to write the updated file at $filePath.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to filter stable versions from a list of versions.
|
||||
*/
|
||||
function filterStableVersions(array $versions): array {
|
||||
return array_filter($versions, function($version) {
|
||||
// Only include stable versions (exclude versions with -rc, -beta, -alpha, etc.)
|
||||
return preg_match('/^\d+\.\d+\.\d+$/', $version);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the latest and previous minor/major versions from a list of versions.
|
||||
*/
|
||||
function getLatestAndPreviousMinorMajorVersions(array $versions): array {
|
||||
usort($versions, 'version_compare');
|
||||
$currentVersion = end($versions);
|
||||
|
||||
$previousVersion = null;
|
||||
foreach (array_reverse($versions) as $version) {
|
||||
if (version_compare($version, $currentVersion, '<') && getMinorMajorVersion($version) !== getMinorMajorVersion($currentVersion)) {
|
||||
$previousVersion = $version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [$currentVersion, $previousVersion];
|
||||
}
|
||||
|
||||
function getMinorMajorVersion(string $version): string {
|
||||
$parts = explode('.', $version);
|
||||
return $parts[0] . '.' . $parts[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to fetch tags from a GitHub repository.
|
||||
*/
|
||||
function fetchGitHubTags(string $repo, string $token, int $page = 1, int $limit = 50): array {
|
||||
$url = "https://api.github.com/repos/$repo/tags?per_page=$limit&page=$page";
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); // GitHub API requires a user agent
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
"Authorization: token $token"
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($response === false) {
|
||||
die("Failed to fetch tags from GitHub.");
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
|
||||
if (isset($data['message']) && $data['message'] == 'Not Found') {
|
||||
die("Repository not found or access denied.");
|
||||
}
|
||||
|
||||
return array_column($data, 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Function saving versions to a temporary files.
|
||||
* File containing latest version is prefixed with 'latest_' and previous version is prefixed with 'previous_'.
|
||||
*/
|
||||
function saveVersionsToFiles(?string $latestVersion, ?string $previousVersion, string $fileNameSuffix): void {
|
||||
file_put_contents("/tmp/latest_{$fileNameSuffix}", $latestVersion);
|
||||
file_put_contents("/tmp/previous_{$fileNameSuffix}", $previousVersion);
|
||||
}
|
||||
|
||||
function replaceLatestVersion(string $latestVersion, string $downloadCommand): void {
|
||||
replaceVersionInFile(
|
||||
__DIR__ . '/../../../.circleci/config.yml',
|
||||
'/(.\/do ' . $downloadCommand . ' )\d+\.\d+\.\d+/',
|
||||
'${1}' . $latestVersion
|
||||
);
|
||||
}
|
||||
|
||||
function replacePreviousVersion(string $previousVersion, string $configParameterName): void {
|
||||
replaceVersionInFile(
|
||||
__DIR__ . '/../../../.circleci/config.yml',
|
||||
'/(' . $configParameterName . ': )\d+\.\d+\.\d+/',
|
||||
'${1}' . $previousVersion
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function replacing the latest and previous versions of a private plugin in the config file.
|
||||
* The function fetches the tags from the GitHub repository, filters stable versions,
|
||||
* gets the latest and previous minor/major versions, and replaces the versions in the CircleCI config file.
|
||||
*/
|
||||
function replacePrivatePluginVersion(
|
||||
string $repository,
|
||||
string $downloadCommand,
|
||||
string $configParameterName,
|
||||
string $versionsFilename
|
||||
): void {
|
||||
// Read the GitHub token from environment variable
|
||||
$token = getenv('GH_TOKEN');
|
||||
if (!$token) {
|
||||
die("GitHub token not found. Make sure it's set in the environment variable 'GH_TOKEN'.");
|
||||
}
|
||||
|
||||
$page = 1;
|
||||
$latestVersion = null;
|
||||
$previousVersion = null;
|
||||
$allVersions = [];
|
||||
while (($latestVersion === null || $previousVersion === null) && $page < 10) {
|
||||
$allVersions = array_merge($allVersions, fetchGitHubTags($repository, $token, $page));
|
||||
$stableVersions = filterStableVersions($allVersions);
|
||||
[$latestVersion, $previousVersion] = getLatestAndPreviousMinorMajorVersions($stableVersions);
|
||||
$page++;
|
||||
}
|
||||
|
||||
echo "Latest version: $latestVersion\n";
|
||||
echo "Previous version: $previousVersion\n";
|
||||
|
||||
if ($latestVersion) {
|
||||
echo "Replacing the latest version in the config file...\n";
|
||||
replaceLatestVersion($latestVersion, $downloadCommand);
|
||||
} else {
|
||||
echo "No latest version found.\n";
|
||||
}
|
||||
|
||||
if ($previousVersion) {
|
||||
echo "Replacing the previous version in the config file...\n";
|
||||
replacePreviousVersion($previousVersion, $configParameterName);
|
||||
} else {
|
||||
echo "No previous version found.\n";
|
||||
}
|
||||
|
||||
saveVersionsToFiles($latestVersion, $previousVersion, $versionsFilename);
|
||||
}
|
182
.github/workflows/update-wordpress-and-plugins.yml
vendored
182
.github/workflows/update-wordpress-and-plugins.yml
vendored
@ -1,182 +0,0 @@
|
||||
name: Check new versions of plugins and WordPress
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 6 * * 1' # At 06:00 on Monday
|
||||
workflow_dispatch: # Allows manual triggering
|
||||
|
||||
jobs:
|
||||
check-versions:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3' # Specify the PHP version you want to use
|
||||
|
||||
# Updating used WordPress
|
||||
- name: Check WordPress Docker Versions
|
||||
run: php .github/workflows/scripts/check_wordpress_versions.php
|
||||
|
||||
- name: Check for WordPress changes
|
||||
id: check_wp_changes
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
if [ "$(git status --porcelain)" != "" ]; then
|
||||
echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||
echo "WORDPRESS_CHANGES=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Get WordPress versions from files
|
||||
id: get_wp_versions
|
||||
run: |
|
||||
echo "WORDPRESS_LATEST_VERSION=$(cat /tmp/latest_wordpress_version.txt)" >> $GITHUB_ENV
|
||||
echo "WORDPRESS_PREVIOUS_VERSION=$(cat /tmp/previous_wordpress_version.txt)" >> $GITHUB_ENV
|
||||
|
||||
- name: Commit WordPress changes
|
||||
if: env.WORDPRESS_CHANGES == 'true'
|
||||
run: |
|
||||
git add .
|
||||
git commit -m $'Update used WordPress images in Circle CI\n\n - latest version: ${{ env.WORDPRESS_LATEST_VERSION }}\n - previous version: ${{ env.WORDPRESS_PREVIOUS_VERSION }}'
|
||||
|
||||
# Updating used WooCommerce plugin
|
||||
- name: Check WooCommerce Versions
|
||||
run: php .github/workflows/scripts/check_woocommerce_versions.php
|
||||
|
||||
- name: Check for WooCommerce changes
|
||||
id: check_wc_changes
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
if [ "$(git status --porcelain)" != "" ]; then
|
||||
echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||
echo "WOOCOMMERCE_CHANGES=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Get WooCommerce versions from files
|
||||
id: get_wc_versions
|
||||
run: |
|
||||
echo "WOOCOMMERCE_LATEST_VERSION=$(cat /tmp/latest_woocommerce_version.txt)" >> $GITHUB_ENV
|
||||
echo "WOOCOMMERCE_PREVIOUS_VERSION=$(cat /tmp/previous_woocommerce_version.txt)" >> $GITHUB_ENV
|
||||
|
||||
- name: Commit WooCommerce changes
|
||||
if: env.WOOCOMMERCE_CHANGES == 'true'
|
||||
run: |
|
||||
git add .
|
||||
git commit -m $'Update used WooCommerce plugin in Circle CI\n\n - latest version: ${{ env.WOOCOMMERCE_LATEST_VERSION }}\n - previous version: ${{ env.WOOCOMMERCE_PREVIOUS_VERSION }}'
|
||||
|
||||
# Updating used Automate Woo plugin
|
||||
- name: Check Automate Woo Versions
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: php .github/workflows/scripts/check_automate_woo_versions.php
|
||||
|
||||
- name: Check for Automate Woo changes
|
||||
id: check_aw_changes
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
if [ "$(git status --porcelain)" != "" ]; then
|
||||
echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||
echo "AUTOMATE_WOO_CHANGES=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Get Automate Woo versions from files
|
||||
id: get_aw_versions
|
||||
run: |
|
||||
echo "AUTOMATE_WOO_LATEST_VERSION=$(cat /tmp/latest_automate_woo_version.txt)" >> $GITHUB_ENV
|
||||
echo "AUTOMATE_WOO_PREVIOUS_VERSION=$(cat /tmp/previous_automate_woo_version.txt)" >> $GITHUB_ENV
|
||||
|
||||
- name: Commit Automate Woo changes
|
||||
if: env.AUTOMATE_WOO_CHANGES == 'true'
|
||||
run: |
|
||||
git add .
|
||||
git commit -m $'Update used Automate Woo plugin in Circle CI\n\n - latest version: ${{ env.AUTOMATE_WOO_LATEST_VERSION }}\n - previous version: ${{ env.AUTOMATE_WOO_PREVIOUS_VERSION }}'
|
||||
|
||||
# Updating used WooCommerce Subscriptions plugin
|
||||
- name: Check WooCommerce Subscriptions Versions
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: php .github/workflows/scripts/check_woocommerce_subscriptions_versions.php
|
||||
|
||||
- name: Check for WooCommerce Subscriptions changes
|
||||
id: check_ws_changes
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
if [ "$(git status --porcelain)" != "" ]; then
|
||||
echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||
echo "SUBSCRIPTIONS_CHANGES=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Get WooCommerce Subscriptions versions from files
|
||||
id: get_ws_versions
|
||||
run: |
|
||||
echo "WOOCOMMERCE_SUBSCRIPTIONS_LATEST_VERSION=$(cat /tmp/latest_woocommerce_subscriptions_version.txt)" >> $GITHUB_ENV
|
||||
echo "WOOCOMMERCE_SUBSCRIPTIONS_PREVIOUS_VERSION=$(cat /tmp/previous_woocommerce_subscriptions_version.txt)" >> $GITHUB_ENV
|
||||
|
||||
- name: Commit WooCommerce Subscriptions changes
|
||||
if: env.SUBSCRIPTIONS_CHANGES == 'true'
|
||||
run: |
|
||||
git add .
|
||||
git commit -m $'Update used WooCommerce Subscriptions plugin in Circle CI\n\n - latest version: ${{ env.WOOCOMMERCE_SUBSCRIPTIONS_LATEST_VERSION }}\n - previous version: ${{ env.WOOCOMMERCE_SUBSCRIPTIONS_PREVIOUS_VERSION }}'
|
||||
|
||||
# Updating used WooCommerce Memberships plugin
|
||||
- name: Check WooCommerce Memberships Versions
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: php .github/workflows/scripts/check_woocommerce_memberships_versions.php
|
||||
|
||||
- name: Check for WooCommerce Memberships changes
|
||||
id: check_wm_changes
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
if [ "$(git status --porcelain)" != "" ]; then
|
||||
echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||
echo "MEMBERSHIPS_CHANGES=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Get WooCommerce Memberships versions from files
|
||||
id: get_wm_versions
|
||||
run: |
|
||||
echo "WOOCOMMERCE_MEMBERSHIPS_LATEST_VERSION=$(cat /tmp/latest_woocommerce_memberships_version.txt)" >> $GITHUB_ENV
|
||||
echo "WOOCOMMERCE_MEMBERSHIPS_PREVIOUS_VERSION=$(cat /tmp/previous_woocommerce_memberships_version.txt)" >> $GITHUB_ENV
|
||||
|
||||
- name: Commit WooCommerce Memberships changes
|
||||
if: env.MEMBERSHIPS_CHANGES == 'true'
|
||||
run: |
|
||||
git add .
|
||||
git commit -m $'Update used WooCommerce Memberships plugin in Circle CI\n\n - latest version: ${{ env.WOOCOMMERCE_MEMBERSHIPS_LATEST_VERSION }}\n - previous version: ${{ env.WOOCOMMERCE_MEMBERSHIPS_PREVIOUS_VERSION }}'
|
||||
|
||||
# Push all changes at the end if any changes were detected
|
||||
#
|
||||
# For local testing with act tool add following:
|
||||
# env:
|
||||
# GH_PAT: ${{ secrets.GH_TOKEN }}
|
||||
# run: |
|
||||
# git remote set-url origin https://${GH_PAT}@github.com/mailpoet/mailpoet
|
||||
# git push -f origin HEAD:refs/heads/update-plugins-and-wordpress-test
|
||||
- name: Push changes
|
||||
if: env.CHANGES_DETECTED == 'true'
|
||||
run: |
|
||||
git push -f origin HEAD:refs/heads/update-plugins-and-wordpress
|
||||
|
||||
# Create a pull request if there are changes
|
||||
- name: Create Pull Request
|
||||
if: env.CHANGES_DETECTED == 'true'
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
branch: update-plugins-and-wordpress
|
||||
title: Update WordPress and plugins in CI jobs
|
||||
base: trunk
|
||||
labels: automated, check-versions
|
||||
body: |
|
||||
1. If all checks passed, you can merge this PR.
|
||||
2. If the build failed, please investigate the failure and either address the issues or delegate the job. Then, make sure these changes are merged.
|
@ -1,27 +0,0 @@
|
||||
name: Add link to WordPress Playground preview
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
add-wp-playground-link:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check and append description
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
PR_NUMBER="${{ github.event.pull_request.number }}"
|
||||
BRANCH_NAME="${{ github.head_ref }}"
|
||||
DESCRIPTION="$(gh pr view $PR_NUMBER --json body -q .body)"
|
||||
HEADING="## Preview"
|
||||
CONTENT="$(printf "${HEADING}\n\n[Preview in WordPress Playground](https://account.mailpoet.com/playground/new/branch:${BRANCH_NAME})\n\n_The latest successful build from \`${BRANCH_NAME}\` will be used. If none is available, the link won't work._")"
|
||||
|
||||
if [[ "$DESCRIPTION" != *"$HEADING"* ]]; then
|
||||
gh pr edit $PR_NUMBER --body "$(printf "${DESCRIPTION}\n\n${CONTENT}")"
|
||||
fi
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -7,7 +7,4 @@ docker-compose.override.yml
|
||||
node_modules
|
||||
npm-debug.log
|
||||
mailpoet-premium
|
||||
tsconfig.tsbuildinfo
|
||||
/wordpress
|
||||
packages/php/*/vendor
|
||||
tests_env/vendor
|
||||
wordpress
|
||||
|
@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. "$(dirname "$0")/../mailpoet/.env"
|
||||
|
||||
export MP_GIT_HOOKS_ENABLE="${MP_GIT_HOOKS_ENABLE:-true}"
|
||||
export MP_GIT_HOOKS_ESLINT="${MP_GIT_HOOKS_ESLINT:-true}"
|
||||
export MP_GIT_HOOKS_STYLELINT="${MP_GIT_HOOKS_STYLELINT:-true}"
|
||||
export MP_GIT_HOOKS_PHPLINT="${MP_GIT_HOOKS_PHPLINT:-true}"
|
||||
export MP_GIT_HOOKS_CODE_SNIFFER="${MP_GIT_HOOKS_CODE_SNIFFER:-true}"
|
||||
export MP_GIT_HOOKS_PHPSTAN="${MP_GIT_HOOKS_PHPSTAN:-true}"
|
||||
export MP_GIT_HOOKS_INSTALL_JS="${MP_GIT_HOOKS_INSTALL_JS:-false}"
|
||||
export MP_GIT_HOOKS_INSTALL_PHP="${MP_GIT_HOOKS_INSTALL_PHP:-false}"
|
||||
|
||||
fileChanged() {
|
||||
local filePattern="$1"
|
||||
local changedFiles="$2"
|
||||
if echo "$changedFiles" | grep -qE "$filePattern"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
installIfUpdates() {
|
||||
local changedFiles="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)"
|
||||
|
||||
if [ "$MP_GIT_HOOKS_INSTALL_JS" = "true" ] && fileChanged "pnpm-lock.yaml" "$changedFiles"; then
|
||||
echo "Change detected in pnpm-lock.yaml, running do install:js"
|
||||
pushd mailpoet
|
||||
./do install:js
|
||||
popd
|
||||
fi
|
||||
|
||||
if [ "$MP_GIT_HOOKS_INSTALL_PHP" = "true" ] && fileChanged "mailpoet/composer.lock" "$changedFiles"; then
|
||||
echo "Change detected in mailpoet/composer.lock, running do install:php"
|
||||
pushd mailpoet
|
||||
./do install:php
|
||||
popd
|
||||
fi
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
. "$(dirname "$0")/common.sh"
|
||||
[ "$MP_GIT_HOOKS_ENABLE" != "true" ] && exit 0
|
||||
|
||||
installIfUpdates
|
||||
|
||||
./do cleanup:cached-files
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
. "$(dirname "$0")/common.sh"
|
||||
[ "$MP_GIT_HOOKS_ENABLE" != "true" ] && exit 0
|
||||
|
||||
|
||||
installIfUpdates
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
. "$(dirname "$0")/common.sh"
|
||||
[ "$MP_GIT_HOOKS_ENABLE" != "true" ] && exit 0
|
||||
|
||||
|
||||
installIfUpdates
|
@ -1,8 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/common.sh"
|
||||
[ "$MP_GIT_HOOKS_ENABLE" != "true" ] && exit 0
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged -c mailpoet/package.json --cwd mailpoet
|
||||
npx lint-staged -c package.json
|
||||
npx lint-staged -c packages/js/email-editor/package.json --cwd packages/js/email-editor
|
||||
npx lint-staged -c packages/php/email-editor/.lintstagedrc.json --cwd packages/php/email-editor
|
||||
cd mailpoet && npx lint-staged
|
||||
|
@ -1,22 +0,0 @@
|
||||
function readPackage(pkg) {
|
||||
// Resolve @wordpress/* dependencies of @woocommerce packages to those used by MailPoet.
|
||||
// This avoids their duplication and downgrading due to @woocommerce pinning them to wp-6.0.
|
||||
// This should be removed once we adopt similar pinning strategy and use dependency extraction.
|
||||
// See: https://github.com/woocommerce/woocommerce/pull/37034
|
||||
if (pkg.name?.startsWith('@woocommerce/')) {
|
||||
pkg.dependencies = Object.fromEntries(
|
||||
Object.entries(pkg.dependencies).map(([name, version]) =>
|
||||
name.startsWith('@wordpress/') || name.startsWith('@types/wordpress__')
|
||||
? [name, '*']
|
||||
: [name, version],
|
||||
),
|
||||
);
|
||||
}
|
||||
return pkg;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hooks: {
|
||||
readPackage,
|
||||
},
|
||||
};
|
@ -1,29 +0,0 @@
|
||||
*.hbs
|
||||
.mp_svn
|
||||
_generated
|
||||
_output
|
||||
composer.json
|
||||
composer.lock
|
||||
node_modules
|
||||
pnpm-lock.yaml
|
||||
vendor
|
||||
vendor-prefixed
|
||||
/.mp_svn
|
||||
/dev/data
|
||||
/mailpoet/assets/dist
|
||||
/mailpoet/assets/js/lib
|
||||
/mailpoet/assets/js/src/newsletter-editor/behaviors/tinymce-icons.js
|
||||
/mailpoet/generated
|
||||
/mailpoet/lang
|
||||
/mailpoet/lib/Newsletter/Renderer/Template.html
|
||||
/mailpoet/lib-3rd-party
|
||||
/mailpoet/plugin_repository
|
||||
/mailpoet/temp
|
||||
/mailpoet/tests/javascript-newsletter-editor/testBundles
|
||||
/mailpoet/tests/plugins
|
||||
/mailpoet/tools/wpscan-semgrep-rules
|
||||
/mailpoet/views
|
||||
/mailpoet-premium
|
||||
/wordpress
|
||||
/packages/php/email-editor
|
||||
/packages/js/email-editor
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
settings:
|
||||
depth: 1
|
||||
|
||||
steps:
|
||||
build:
|
||||
image: node:current-bookworm-slim
|
||||
commands:
|
||||
- apt update
|
||||
- apt install php php-symfony bash -y
|
||||
- npm install pnpm
|
||||
- cd mailpoet
|
||||
- bash build.sh
|
||||
- mkdir ../output
|
||||
- mv mailpoet.zip ../output
|
||||
- cd ..
|
||||
|
||||
release:
|
||||
image: woodpeckerci/plugin-gitea-release:latest
|
||||
settings:
|
||||
base_url: https://git.cavemanon.xyz
|
||||
api_key:
|
||||
from_secret: releasesmithapikey
|
||||
files: "output/"
|
||||
prerelease: false
|
||||
title: "${CI_COMMIT_TAG}"
|
||||
when:
|
||||
- event: tag
|
@ -1,51 +1,50 @@
|
||||
# Contributing
|
||||
|
||||
There is a `./do` command that helps with the development process. See [README](README.md) for more details.
|
||||
|
||||
## PHP Code
|
||||
|
||||
- Two spaces indentation.
|
||||
- Space between keyword and left bracket (`if ()`, `for ()`, `switch ()`...).
|
||||
- `CamelCase` for classes.
|
||||
- `camelCase` for methods.
|
||||
- `snake_case` for variables and class properties.
|
||||
- Space between keyword (if, for, switch...) and left bracket
|
||||
- CamelCase for classes.
|
||||
- camelCase for methods.
|
||||
- snake_case for variables and class properties.
|
||||
- Composition over Inheritance.
|
||||
- Comments are a code smell. If you need to use a comment - see if same idea can be achieved by more clearly expressing code.
|
||||
- Require other classes with `use` at the beginning of the class file.
|
||||
- Require other classes with 'use' at the beginning of the class file.
|
||||
- Do not specify 'public' if method is public, it's implicit.
|
||||
- Always use guard clauses.
|
||||
- Ensure compatibility with PHP 7.4 and newer versions.
|
||||
- Ensure compatibility with PHP 7.1 and newer versions.
|
||||
- Cover your code in tests.
|
||||
|
||||
## SCSS Code
|
||||
|
||||
- `kebab-case` for file names.
|
||||
- Components files are prefixed with underscore, to indicate, that they aren't compiled separately (`_new-component.scss`).
|
||||
- camelCase for file name
|
||||
- Components files are prefixed with underscore, to indicate, that they aren't compiled separately.
|
||||
|
||||
## JS Code
|
||||
|
||||
- Javascript code should follow the [Airbnb style guide](https://github.com/airbnb/javascript).
|
||||
- Prefer named export before default export in JS and TS files
|
||||
- Default to TypeScript for new files.
|
||||
|
||||
## Disabling linting rules
|
||||
|
||||
- We want to avoid using `eslint-disable`
|
||||
- If we have to use it we need to use a comment explaining why do we need it:
|
||||
`/* eslint-disable no-new -- this class has a side-effect in the constructor and it's a library's. */`
|
||||
- For PHP we do the same with the exception `// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps` which for now doesn’t require an explanation
|
||||
- we want to avoid using `eslint-disable`
|
||||
- if we have to use it we need to use a comment explaining why do we need it:
|
||||
`/* eslint-disable no-new -- this class has a side-effect in the constructor and it's a library's. */`
|
||||
- for PHP we do the same with the exception `// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps` which for now doesn’t require an explanation
|
||||
|
||||
## Git flow
|
||||
|
||||
- Do not commit to trunk.
|
||||
- Do not commit to master.
|
||||
- Open a short-living feature branch.
|
||||
- Use good commit messages as explained here https://chris.beams.io/posts/git-commit. Include Jira ticket in the commit message.
|
||||
- Open a pull request.
|
||||
- Add Jira issue reference in the title of the Pull Request.
|
||||
- Work on the pull request.
|
||||
- Use the `./do qa` command to check your code style before pushing.
|
||||
- Create a pull request when finished. Include Jira ticket in the title of the pull request.
|
||||
- Use good commit messages as explained here https://chris.beams.io/posts/git-commit
|
||||
- Wait for review from another developer.
|
||||
|
||||
## Feature flags
|
||||
## Issues creation
|
||||
- Issues are managed on Jira.
|
||||
- Discuss issues on public Slack chats, discuss code in pull requests.
|
||||
- Open a small Jira issue only when it has been discussed.
|
||||
|
||||
We use feature flags to control the visibility of new features. This allows us to work on new features in smaller chunks before they are released to all customers.
|
||||
## Migration from IdiORM to Doctrine
|
||||
MailPoet used to use [IdiORM](https://github.com/j4mie/idiorm) as its object-relational mapper (ORM), but the project was abandoned a while ago, so we started a migration to [Doctrine](https://www.doctrine-project.org/). This is a significant effort that has been going on for quite some time. Although you will still see parts of the code that use IdioORM, we ask that all new code be added using Doctrine instead.
|
||||
|
||||
All IdioORM models live in [mailpoet/lib/Models](https://github.com/mailpoet/mailpoet/tree/master/mailpoet/lib/Models), should be considered deprecated and shouldn't be used by new code. We are moving everything to Doctrine entities and some auxiliary code when needed. You can find Doctrine entities in [mailpoet/lib/Entities](https://github.com/mailpoet/mailpoet/tree/master/mailpoet/lib/Entities).
|
||||
|
||||
- Feature flags can be enabled on the experimental page: `/admin.php?page=mailpoet-experimental`.
|
||||
- New feature flags can be added in the class `FeaturesController`.
|
||||
|
156
README.md
156
README.md
@ -1,52 +1,17 @@
|
||||
### Table of Contents
|
||||
|
||||
1. [MailPoet](#mailpoet)
|
||||
2. [Initial setup](#initial-setup)
|
||||
1. [Additional dependencies](#additional-dependencies)
|
||||
3. [Xdebug](#xdebug)
|
||||
1. [PhpStorm setup](#phpstorm-setup)
|
||||
2. [Xdebug develop mode](#xdebug-develop-mode)
|
||||
3. [Xdebug for integration tests](#xdebug-for-integration-tests)
|
||||
4. [Local development](#local-development)
|
||||
1. [NFS volume sharing for Mac](#nfs-volume-sharing-for-mac)
|
||||
2. [Husky hooks](#husky-hooks)
|
||||
5. [Docker](#docker)
|
||||
1. [Commands](#commands)
|
||||
2. [Available PHP versions](#available-php-versions)
|
||||
3. [Disabling the Tracy panel](#disabling-the-tracy-panel)
|
||||
4. [Running individual tests](#running-individual-tests)
|
||||
6. [TODO](#todo)
|
||||
|
||||
## MailPoet
|
||||
|
||||
# MailPoet
|
||||
The **MailPoet** plugin monorepo.
|
||||
|
||||
If you have **any questions or need help or support**, please see the [Support](SUPPORT.md) document.
|
||||
|
||||
To use our Docker-based development environment (recommended), continue with the steps below.
|
||||
If you'd like to use the plugin code directly, see details in [the plugin's readme](mailpoet/README.md).
|
||||
|
||||
## Initial setup
|
||||
## 🔌 Initial setup
|
||||
1) Run `./do setup` to pull everything and install necessary dependencies.
|
||||
2) Add secrets to `.env` files in `mailpoet` and `mailpoet-premium` directories. Go to the Secret Store and look for "MailPoet: plugin .env"
|
||||
3) Run `./do start` to start the stack.
|
||||
4) Go to http://localhost:8888 to see the dashboard of the dev environment.
|
||||
|
||||
1. Run `./do setup` to pull everything and install necessary dependencies.
|
||||
2. Add secrets to `.env` files in `mailpoet` and `mailpoet-premium` directories. Go to the Secret Store and look for "MailPoet: plugin .env"
|
||||
3. Run `./do start` to start the stack.
|
||||
4. Go to http://localhost:8888 to see the dashboard of the dev environment.
|
||||
|
||||
### Additional dependencies
|
||||
|
||||
Even though it's possible to run everything using Docker, in the development workflow,
|
||||
it may be faster and more convenient to run some tasks outside the container. Therefore,
|
||||
the following tools are recommended:
|
||||
|
||||
1. **PHP** as per `composer.json` requirements.
|
||||
2. **Node.js**, as specified by `.nvmrc`. For automatic management use [nvm](https://github.com/nvm-sh/nvm), [FNM](https://github.com/Schniz/fnm), or [Volta](https://github.com/volta-cli/volta).
|
||||
3. **pnpm**, as specified in `package.json`. For automatic setup enable [Corepack](https://nodejs.org/docs/latest-v17.x/api/corepack.html) using `corepack enable`.
|
||||
|
||||
## Xdebug
|
||||
|
||||
### PhpStorm setup
|
||||
|
||||
## 🔍 PHPStorm setup for XDebug
|
||||
In `Languages & Preferences > PHP > Servers` set path mappings:
|
||||
|
||||
```shell
|
||||
@ -62,8 +27,7 @@ To use XDebug inside the **cron**, you need to pass a URL argument `&XDEBUG_TRIG
|
||||
[in the cron request](https://github.com/mailpoet/mailpoet/blob/bf7bd6d2d9090ed6ec7b8b575bb7d6b08e663a52/lib/Cron/CronHelper.php#L155-L166).
|
||||
Alternatively, you can add `XDEBUG_TRIGGER: yes` to the `wordpress` service in `docker-compose.yml` and restart it (which will run XDebug also for all other requests).
|
||||
|
||||
### Xdebug develop mode
|
||||
|
||||
## Xdebug develop mode
|
||||
[Xdebug develop mode](https://xdebug.org/docs/develop) is disabled by default because it causes performance issues due to conflicts with the DI container.
|
||||
|
||||
It can be enabled when needed using the `XDEBUG_MODE` environment variable. For example, it is possible to enable it by adding the following to `docker-compose.override.yml`:
|
||||
@ -73,62 +37,36 @@ environment:
|
||||
XDEBUG_MODE: debug, develop
|
||||
```
|
||||
|
||||
### Xdebug for integration tests
|
||||
|
||||
- In Languages & Preferences > PHP > Servers create a new sever named `MailPoetTest`, set the host to `localhost` and port to `80` and set following path mappings:
|
||||
|
||||
```shell
|
||||
wordpress -> /wp-core
|
||||
mailpoet -> /wp-core/wp-content/plugins/mailpoet
|
||||
mailpoet-premium -> /wp-core/wp-content/plugins/mailpoet-premium
|
||||
mailpoet/vendor/bin/codecept -> /project/vendor/bin/codecept
|
||||
mailpoet/vendor/bin/wp -> /usr/local/bin/wp
|
||||
```
|
||||
|
||||
- Add `XDEBUG_TRIGGER: 1` environment to `tests_env/docker/docker-compose.yml` -> codeception service to start triggering Xdebug
|
||||
- Make PHPStorm listen to connections by clicking on the phone icon
|
||||
|
||||
## Local development
|
||||
|
||||
### NFS volume sharing for Mac
|
||||
|
||||
## 💾 NFS volume sharing for Mac
|
||||
NFS volumes can bring more stability and performance on Docker for Mac. To setup NFS volume sharing run:
|
||||
|
||||
```shell
|
||||
sudo sh dev/mac-nfs-setup.sh
|
||||
```
|
||||
|
||||
Then create a Docker Compose override file with NFS settings and restart containers:
|
||||
|
||||
```shell
|
||||
cp docker-compose.override.macos-sample.yml docker-compose.override.yml
|
||||
|
||||
docker compose down -v --remove-orphans
|
||||
docker compose up -d
|
||||
docker-compose down -v --remove-orphans
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
**NOTE:** If you are on MacOS Catalina or newer, make sure to put the repository
|
||||
outside your `Documents` folder, otherwise you may run into [file permission issues](https://objekt.click/2019/11/docker-the-problem-with-macos-catalina/).
|
||||
|
||||
### Husky hooks
|
||||
|
||||
# 🐶 Husky
|
||||
We use [Husky](https://github.com/typicode/husky) to run automated checks in pre-commit hooks.
|
||||
|
||||
In case you're using [NVM](https://github.com/nvm-sh/nvm) for Node version management you may
|
||||
need to create or update your `~/.huskyrc` file with:
|
||||
|
||||
```sh
|
||||
# This loads nvm.sh and sets the correct PATH before running the hooks:
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
```
|
||||
|
||||
Without it, you may experience errors in some Git clients.
|
||||
|
||||
## Docker
|
||||
|
||||
### Commands
|
||||
|
||||
## 🕹 Commands
|
||||
The `./do` script define aliases for most of the commands you will need while working on plugins:
|
||||
|
||||
```shell
|
||||
@ -149,70 +87,24 @@ Options:
|
||||
|
||||
You can access this help in your command line running `./do` without parameters.
|
||||
|
||||
### Available PHP versions
|
||||
## ✉️ Adding new templates to the plugin
|
||||
[Read the article.](https://mailpoet.atlassian.net/wiki/spaces/MAILPOET/pages/629374977/Adding+new+templates+to+the+plugin)
|
||||
|
||||
To switch the environment to a different PHP version:
|
||||
|
||||
1. Check https://github.com/mailpoet/mailpoet/tree/trunk/dev for a list of available PHP versions. Each directory starting with `php` corresponds to a available version.
|
||||
2. Configure the `wordpress` service in `docker-compose.override.yml` to build from the desired PHP version Dockerfile (replace {PHP_VERSION} with the name of the directory that corresponds to the version that you want to use):
|
||||
## 🚥 Testing with PHP 7.4 or PHP 8.1
|
||||
To switch the environment to PHP 7.4/8.1:
|
||||
1) Configure the `wordpress` service in `docker-compose.override.yml` to build from the php74 Dockerfile:
|
||||
|
||||
```yaml
|
||||
wordpress:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: dev/{PHP_VERSION}/Dockerfile
|
||||
dockerfile: docker/php74/Dockerfile # OR docker/php81/Dockerfile
|
||||
```
|
||||
3) Run `docker-compose build wordpress`.
|
||||
4) Start the stack with `./do start`.
|
||||
|
||||
3. Run `docker compose build wordpress`.
|
||||
4. Start the stack with `./do start`.
|
||||
|
||||
To switch back to the default PHP version remove what was added in 2) and, run `docker compose build wordpress` for application container and `docker compose build test_wordpress` for tests container,
|
||||
To switch back to PHP 8 remove what was added in 1) and, run `docker-compose build wordpress` for application container and `docker-compose build test_wordpress` for tests container,
|
||||
and start the stack using `./do start`.
|
||||
|
||||
### Disabling the Tracy panel
|
||||
|
||||
To disable the Tracy panel, add the following to `docker-compose.override.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
wordpress:
|
||||
environment:
|
||||
MAILPOET_DISABLE_TRACY_PANEL: 1
|
||||
```
|
||||
|
||||
### Running individual tests
|
||||
|
||||
It's recommended to run tests in Docker. Free plugin tests can be run using --test flag (`./do --test`). However, to run a premium test, you need to ssh into test container (`./do ssh --test`) and run tests there.
|
||||
|
||||
#### Integration test in the free plugin
|
||||
|
||||
```shell
|
||||
./do --test test:integration --skip-deps --file=tests/integration/WP/EmojiTest.php
|
||||
```
|
||||
|
||||
#### Acceptance test in the free plugin
|
||||
|
||||
```shell
|
||||
./do --test test:acceptance --skip-deps --file=tests/acceptance/Misc/MailpoetMenuCest.php
|
||||
```
|
||||
|
||||
#### Unit/integration test in the premium plugin
|
||||
|
||||
```shell
|
||||
./do ssh --test # to enter the container
|
||||
cd ../mailpoet-premium # switch to premium plugin directory
|
||||
./do test:unit --file=tests/unit/Config/EnvTest.php
|
||||
```
|
||||
|
||||
#### Acceptance test in the premium plugin
|
||||
|
||||
```shell
|
||||
cd ./mailpoet-premium # switch to premium plugin directory on your local machine
|
||||
./do test:acceptance --skip-deps --file tests/acceptance/PremiumCheckCest.php
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] Install WooCommerce
|
||||
- [ ] Install Members
|
||||
- [ ] Install other useful plugins by default
|
||||
## ✅ TODO
|
||||
- install woo commerce, members and other useful plugins by default
|
||||
|
24
SUPPORT.md
24
SUPPORT.md
@ -1,5 +1,23 @@
|
||||
# Support
|
||||
# Getting Support
|
||||
|
||||
Please visit our [Support](https://www.mailpoet.com/support/) page. We have a team of Happiness Engineers ready to help you.
|
||||
Welcome to MailPoet!
|
||||
This isn't the right place to get support for using MailPoet,
|
||||
but the following resources are available below,
|
||||
thanks for understanding.
|
||||
|
||||
For feature requests, please use our [tracker](https://feedback.mailpoet.com).
|
||||
- [Support](https://www.mailpoet.com/support)
|
||||
- [Feature Requests](https://feedback.mailpoet.com)
|
||||
|
||||
*DO NOT* use the issue tracker to ask questions;
|
||||
use the links above for that.
|
||||
Questions posed to the issue tracker will be closed.
|
||||
|
||||
When reporting an issue, please include the following details:
|
||||
|
||||
- A narrative description of what you are trying to accomplish.
|
||||
- The expected results.
|
||||
- The actual results received.
|
||||
- We may ask for additional details: what version of the plugin you are using, and what PHP version
|
||||
was used to reproduce the issue.
|
||||
|
||||
You may also submit a failing test case as a pull request.
|
||||
|
@ -1,8 +0,0 @@
|
||||
export default {
|
||||
presets: [
|
||||
['@babel/preset-react', { runtime: 'automatic' }],
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-typescript',
|
||||
],
|
||||
plugins: [['@babel/plugin-transform-runtime']],
|
||||
};
|
@ -1,93 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>MailPoet dev environment</title>
|
||||
<link rel="icon" href="favicon.png" />
|
||||
<style>
|
||||
body {
|
||||
background: #ffe0d0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol';
|
||||
}
|
||||
p {
|
||||
color: #071c6d;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
a {
|
||||
color: #fe5301;
|
||||
transition: all 0.25s ease-in-out;
|
||||
}
|
||||
a:hover {
|
||||
color: #cb4201;
|
||||
}
|
||||
table {
|
||||
margin: 2em auto;
|
||||
}
|
||||
table tr td {
|
||||
color: #071c6d;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
table tr td:nth-child(2) {
|
||||
font-weight: 600;
|
||||
}
|
||||
img {
|
||||
margin: 3em auto 0;
|
||||
width: 250px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>MailPoet dev environment</title>
|
||||
<link rel="icon" href="favicon.png" />
|
||||
<style>
|
||||
body {
|
||||
background: #ffe0d0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
}
|
||||
p {
|
||||
color: #071c6d;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
a {
|
||||
color: #fe5301;
|
||||
transition: all 0.25s ease-in-out;
|
||||
}
|
||||
a:hover {
|
||||
color: #cb4201;
|
||||
}
|
||||
table {
|
||||
margin: 2em auto;
|
||||
}
|
||||
table tr td {
|
||||
color: #071c6d;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
table tr td:nth-child(2) {
|
||||
font-weight: 600;
|
||||
}
|
||||
img {
|
||||
margin: 3em auto 0;
|
||||
width: 250px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a href="/"><img src="logo.svg" /></a>
|
||||
<p>Dev environment</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>🖥</td>
|
||||
<td>
|
||||
<a href="http://localhost:8002">WordPress</a>
|
||||
[<a href="http://localhost:8002/wp-admin/">wp-admin</a>]
|
||||
</td>
|
||||
<td>App for development</td>
|
||||
<td><a href="http://localhost:8002">http://localhost:8002</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>🚥</td>
|
||||
<td>
|
||||
<a href="http://localhost:8003">WordPress Tests</a>
|
||||
[<a href="http://localhost:8003/wp-admin/">wp-admin</a>]
|
||||
</td>
|
||||
<td>App for E2E tests</td>
|
||||
<td><a href="http://localhost:8003">http://localhost:8003</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>💾</td>
|
||||
<td>
|
||||
<a
|
||||
href="http://localhost:8081?server=db&mysql=wordpress&username=wordpress"
|
||||
>Adminer</a
|
||||
>
|
||||
</td>
|
||||
<td>DB management</td>
|
||||
<td>
|
||||
<a
|
||||
href="http://localhost:8081?server=db&mysql=wordpress&username=wordpress"
|
||||
>http://localhost:8081</a
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>📪</td>
|
||||
<td><a href="http://localhost:8082">MailHog</a></td>
|
||||
<td>Email catcher</td>
|
||||
<td><a href="http://localhost:8082">http://localhost:8082</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
<body>
|
||||
<a href="/"><img src="logo.svg" /></a>
|
||||
<p>Dev environment</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>🖥</td>
|
||||
<td>
|
||||
<a href="http://localhost:8002">WordPress</a>
|
||||
[<a href="http://localhost:8002/wp-admin/">wp-admin</a>]
|
||||
</td>
|
||||
<td>App for development</td>
|
||||
<td><a href="http://localhost:8002">http://localhost:8002</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>🚥</td>
|
||||
<td>
|
||||
<a href="http://localhost:8003">WordPress Tests</a>
|
||||
[<a href="http://localhost:8003/wp-admin/">wp-admin</a>]
|
||||
</td>
|
||||
<td>App for E2E tests</td>
|
||||
<td><a href="http://localhost:8003">http://localhost:8003</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>💾</td>
|
||||
<td>
|
||||
<a href="http://localhost:8081?server=db&mysql=wordpress&username=wordpress">Adminer</a>
|
||||
</td>
|
||||
<td>DB management</td>
|
||||
<td>
|
||||
<a href="http://localhost:8081?server=db&mysql=wordpress&username=wordpress">http://localhost:8081</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>📪</td>
|
||||
<td><a href="http://localhost:8082">MailHog</a></td>
|
||||
<td>Email catcher</td>
|
||||
<td><a href="http://localhost:8082">http://localhost:8082</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -21,7 +21,7 @@ mkdir -p wordpress/wp-content/plugins/mailpoet-premium
|
||||
mkdir -p dev/data/mailhog
|
||||
|
||||
for plugin in "mailpoet" "mailpoet-premium"; do
|
||||
docker compose run --rm wordpress /bin/sh -c "
|
||||
docker-compose run --rm wordpress /bin/sh -c "
|
||||
[ -d /var/www/html/wp-content/plugins/$plugin ] &&
|
||||
cd /var/www/html/wp-content/plugins/$plugin &&
|
||||
./do install &&
|
||||
@ -29,7 +29,7 @@ for plugin in "mailpoet" "mailpoet-premium"; do
|
||||
"
|
||||
done
|
||||
|
||||
docker compose run --rm wordpress /bin/sh -c "
|
||||
docker-compose run --rm wordpress /bin/sh -c "
|
||||
cd /var/www/templates &&
|
||||
mkdir assets classes exported
|
||||
"
|
||||
|
@ -29,6 +29,6 @@ cat <<EOT
|
||||
NFS volume sharing is set up. Recreate your containers and volumes using:
|
||||
cp docker-compose.override.macos-sample.yml docker-compose.override.yml
|
||||
|
||||
docker compose down -v --remove-orphans
|
||||
docker compose up -d
|
||||
docker-compose down -v --remove-orphans
|
||||
docker-compose up -d
|
||||
EOT
|
||||
|
@ -5,19 +5,23 @@ ARG GID=1000
|
||||
|
||||
# additinal extensions
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y git zlib1g-dev wget gnupg msmtp gettext zip subversion \
|
||||
&& apt-get install -y git zlib1g-dev wget gnupg msmtp \
|
||||
&& docker-php-ext-install pdo_mysql \
|
||||
&& pecl install xdebug-2.9.8 && \
|
||||
\
|
||||
# Install NodeJS, enable Corepack
|
||||
curl -sL https://deb.nodesource.com/setup_19.x | bash - && \
|
||||
# Install NodeJS + NPM
|
||||
curl -sL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||
apt-get install -y nodejs build-essential && \
|
||||
corepack enable && \
|
||||
\
|
||||
# Install WP-CLI
|
||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
||||
chmod +x /usr/local/bin/wp && \
|
||||
\
|
||||
# Installing Transifex Client
|
||||
apt-get update && \
|
||||
apt-get install -y python3-pip gettext zip subversion && \
|
||||
pip install transifex-client && \
|
||||
\
|
||||
# Clean up
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
@ -36,6 +40,5 @@ RUN cat /tmp/xdebug.ini >> $XDEBUGINI_PATH
|
||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
||||
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
|
||||
|
||||
# ensure existing content in /var/www/html respects UID and GID, give Node permissions for Corepack
|
||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
||||
# ensure existing content in /var/www/html respects UID and GID
|
||||
RUN chown -R ${UID}:${GID} /var/www/html
|
||||
|
@ -5,17 +5,21 @@ ARG GID=1000
|
||||
|
||||
# additinal extensions
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev \
|
||||
&& \
|
||||
# Install NodeJS, enable Corepack
|
||||
curl -sL https://deb.nodesource.com/setup_19.x | bash - && \
|
||||
# Install NodeJS + NPM
|
||||
curl -sL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||
apt-get install -y nodejs build-essential && \
|
||||
corepack enable && \
|
||||
\
|
||||
# Install WP-CLI
|
||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
||||
chmod +x /usr/local/bin/wp && \
|
||||
\
|
||||
# Installing Transifex Client
|
||||
apt-get update && \
|
||||
apt-get install -y python3-pip gettext subversion && \
|
||||
pip3 install transifex-client && \
|
||||
\
|
||||
# Clean up
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
@ -27,7 +31,7 @@ RUN printf "account default\nhost smtp\nport 1025" > /etc/msmtprc
|
||||
|
||||
# xdebug build an config
|
||||
ENV XDEBUGINI_PATH=/usr/local/etc/php/conf.d/xdebug.ini
|
||||
RUN git clone -b "3.3.1" --depth 1 https://github.com/xdebug/xdebug.git /usr/src/php/ext/xdebug \
|
||||
RUN git clone -b "3.0.2" --depth 1 https://github.com/xdebug/xdebug.git /usr/src/php/ext/xdebug \
|
||||
&& docker-php-ext-configure xdebug --enable-xdebug-dev \
|
||||
&& docker-php-ext-install xdebug \
|
||||
&& mkdir /tmp/debug
|
||||
@ -40,6 +44,5 @@ RUN docker-php-ext-install pdo_mysql
|
||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
||||
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
|
||||
|
||||
# ensure existing content in /var/www/html respects UID and GID, give Node permissions for Corepack
|
||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
||||
# ensure existing content in /var/www/html respects UID and GID
|
||||
RUN chown -R ${UID}:${GID} /var/www/html
|
||||
|
@ -5,17 +5,21 @@ ARG GID=1000
|
||||
|
||||
# additinal extensions
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev \
|
||||
&& \
|
||||
# Install NodeJS, enable Corepack
|
||||
curl -sL https://deb.nodesource.com/setup_19.x | bash - && \
|
||||
# Install NodeJS + NPM
|
||||
curl -sL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||
apt-get install -y nodejs build-essential && \
|
||||
corepack enable && \
|
||||
\
|
||||
# Install WP-CLI
|
||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
||||
chmod +x /usr/local/bin/wp && \
|
||||
\
|
||||
# Installing Transifex Client
|
||||
apt-get update && \
|
||||
apt-get install -y python3-pip gettext subversion && \
|
||||
pip3 install transifex-client && \
|
||||
\
|
||||
# Clean up
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
@ -27,7 +31,7 @@ RUN printf "account default\nhost smtp\nport 1025" > /etc/msmtprc
|
||||
|
||||
# xdebug build an config
|
||||
ENV XDEBUGINI_PATH=/usr/local/etc/php/conf.d/xdebug.ini
|
||||
RUN git clone -b "3.3.1" --depth 1 https://github.com/xdebug/xdebug.git /usr/src/php/ext/xdebug \
|
||||
RUN git clone -b "3.1.1" --depth 1 https://github.com/xdebug/xdebug.git /usr/src/php/ext/xdebug \
|
||||
&& docker-php-ext-configure xdebug --enable-xdebug-dev \
|
||||
&& docker-php-ext-install xdebug \
|
||||
&& mkdir /tmp/debug
|
||||
@ -40,6 +44,5 @@ RUN docker-php-ext-install pdo_mysql
|
||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
||||
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
|
||||
|
||||
# ensure existing content in /var/www/html respects UID and GID, give Node permissions for Corepack
|
||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
||||
# ensure existing content in /var/www/html respects UID and GID
|
||||
RUN chown -R ${UID}:${GID} /var/www/html
|
||||
|
@ -1,46 +0,0 @@
|
||||
FROM wordpress:php8.2-apache
|
||||
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
|
||||
# additinal extensions
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y git zlib1g-dev libzip-dev zip wget gnupg msmtp libpng-dev gettext subversion \
|
||||
&& \
|
||||
# Install NodeJS, enable Corepack
|
||||
curl -sL https://deb.nodesource.com/setup_19.x | bash - && \
|
||||
apt-get install -y nodejs build-essential && \
|
||||
corepack enable && \
|
||||
\
|
||||
# Install WP-CLI
|
||||
curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && \
|
||||
chmod +x /usr/local/bin/wp && \
|
||||
\
|
||||
# Clean up
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
COPY dev/php.ini /usr/local/etc/php/conf.d/php_user.ini
|
||||
|
||||
# msmtp config
|
||||
RUN printf "account default\nhost smtp\nport 1025" > /etc/msmtprc
|
||||
|
||||
# xdebug build an config
|
||||
ENV XDEBUGINI_PATH=/usr/local/etc/php/conf.d/xdebug.ini
|
||||
RUN git clone -b "3.3.1" --depth 1 https://github.com/xdebug/xdebug.git /usr/src/php/ext/xdebug \
|
||||
&& docker-php-ext-configure xdebug --enable-xdebug-dev \
|
||||
&& docker-php-ext-install xdebug \
|
||||
&& mkdir /tmp/debug
|
||||
COPY dev/xdebug.ini /tmp/xdebug.ini
|
||||
RUN cat /tmp/xdebug.ini >> $XDEBUGINI_PATH
|
||||
|
||||
# php extensions
|
||||
RUN docker-php-ext-install pdo_mysql
|
||||
RUN docker-php-ext-install mysqli
|
||||
|
||||
# allow .htaccess files (between <Directory /var/www/> and </Directory>, which is WordPress installation)
|
||||
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
|
||||
|
||||
# ensure existing content in /var/www/html respects UID and GID, give Node permissions for Corepack
|
||||
RUN chown -R ${UID}:${GID} /var/www/html && \
|
||||
mkdir -p /.node && chown -R ${UID}:${GID} /.node
|
25
do
25
do
@ -3,8 +3,8 @@
|
||||
function syntax {
|
||||
cat << EOF
|
||||
./do setup Setup the dev environment.
|
||||
./do start Start the docker containers (docker compose up -d).
|
||||
./do stop Stop the docker containers (docker compose stop).
|
||||
./do start Start the docker containers (docker-compose up -d).
|
||||
./do stop Stop the docker containers (docker-compose stop).
|
||||
./do ssh [--test] Run an interactive bash shell inside the plugin directory.
|
||||
./do run [--test] <command> Run a custom bash command in the wordpress container.
|
||||
./do acceptance [--premium] Run acceptance tests.
|
||||
@ -21,7 +21,7 @@ EOF
|
||||
function ssh_and_run {
|
||||
params=("$@")
|
||||
params=("${params[@]:1}")
|
||||
docker compose exec $1 bash -c "${params[@]}"
|
||||
docker-compose exec $1 bash -c "${params[@]}"
|
||||
}
|
||||
|
||||
if [ "$1" = "" -o "$1" = "--help" ]; then
|
||||
@ -31,10 +31,10 @@ elif [ "$1" = "setup" ]; then
|
||||
./dev/initial-setup.sh
|
||||
|
||||
elif [ "$1" = "start" ]; then
|
||||
docker compose up -d
|
||||
docker-compose up -d
|
||||
|
||||
elif [ "$1" = "stop" ]; then
|
||||
docker compose stop
|
||||
docker-compose stop
|
||||
|
||||
elif [ "$1" = "run" ]; then
|
||||
params=("$@")
|
||||
@ -54,9 +54,9 @@ elif [ "$1" = "ssh" ]; then
|
||||
fi
|
||||
|
||||
if [ "$2" = "--test" ] || [ "$3" = "--test" ]; then
|
||||
docker compose exec --workdir $dir test_wordpress bash
|
||||
docker-compose exec --workdir $dir test_wordpress bash
|
||||
else
|
||||
docker compose exec --workdir $dir wordpress bash
|
||||
docker-compose exec --workdir $dir wordpress bash
|
||||
fi
|
||||
|
||||
elif [ "$1" = "acceptance" ]; then
|
||||
@ -65,7 +65,7 @@ elif [ "$1" = "acceptance" ]; then
|
||||
else
|
||||
cd mailpoet
|
||||
fi
|
||||
COMPOSE_HTTP_TIMEOUT=200 docker compose run codeception_acceptance -e KEEP_DEPS=1 --steps --debug -vvv
|
||||
COMPOSE_HTTP_TIMEOUT=200 docker-compose run codeception -e KEEP_DEPS=1 --steps --debug -vvv
|
||||
cd ..
|
||||
|
||||
elif [ "$1" = "build" ]; then
|
||||
@ -82,16 +82,13 @@ else
|
||||
docker_service="wordpress"
|
||||
plugin_directory="mailpoet"
|
||||
params=("$@")
|
||||
|
||||
if [ "$1" = "--test" -o "$2" = "--test" ]; then
|
||||
if [ "$1" = "--test" -o "$2" = "--test" ]; then
|
||||
docker_service="test_wordpress"
|
||||
params=("${params[@]:1}")
|
||||
cd mailpoet
|
||||
./do ${params[*]}
|
||||
exit 1
|
||||
fi
|
||||
if [ "$1" = "--premium" -o "$2" = "--premium" ]; then
|
||||
plugin_directory="mailpoet-premium"
|
||||
params=("${params[@]:1}")
|
||||
fi
|
||||
ssh_and_run $docker_service "cd wp-content/plugins/$plugin_directory && ./do ${params[*]}"
|
||||
ssh_and_run $docker_service "cd wp-content/plugins/$plugin_directory && ./do ${params[@]}"
|
||||
fi
|
||||
|
@ -1,48 +1,36 @@
|
||||
# MailPoet – Documentation for Integrators
|
||||
# MailPoet 3 - Documentation for Integrators
|
||||
|
||||
This is a place where we put documentation for developers who want to build an extension for MailPoet plugin.
|
||||
This is a place where we put documentation for developers who want to build an extension for MailPoet 3 plugin.
|
||||
If you are a user looking for a user guide please visit our [knowledge base](https://kb.mailpoet.com/).
|
||||
|
||||
## MailPoet API
|
||||
|
||||
MailPoet API is the officially supported way to integrate with the MailPoet plugin. It focuses on functionality for managing subscribers.
|
||||
Developers integrating MailPoet functionality in their own plugins or projects are strongly discouraged against using other functions and classes within MailPoet codebase! We are continually refactoring as part of our rapid development process, and backward compatibility is not guaranteed.
|
||||
MailPoet API is the officially supported way to integrate with the MailPoet 3 plugin. It focuses on functionality for managing subscribers.
|
||||
Developers integrating MailPoet functionality in their own plugins or projects are strongly discouraged against using other functions and classes within MailPoet codebase! We are continually refactoring as part of our rapid development process, and backward compatibility is not guaranteed.
|
||||
|
||||
### Basics
|
||||
|
||||
MailPoet API is distributed within MailPoet3 plugin and it is implemented as a PHP class.
|
||||
Currently supported version is `v1`.
|
||||
|
||||
### Instantiation
|
||||
|
||||
```php
|
||||
if (class_exists(\MailPoet\API\API::class)) {
|
||||
$mailpoet_api = \MailPoet\API\API::MP('v1');
|
||||
}
|
||||
```
|
||||
|
||||
Class `\MailPoet\API\API` becomes available once MailPoet plugin is loaded by WordPress.
|
||||
|
||||
### Available API Methods
|
||||
|
||||
- [Add List (addList)](api_methods/AddList.md)
|
||||
- [Add Subscriber (addSubscriber)](api_methods/AddSubscriber.md)
|
||||
- [Update Subscriber (updateSubscriber)](api_methods/UpdateSubscriber.md)
|
||||
- [Add Subscriber Field (addSubscriberField)](api_methods/AddSubscriberField.md)
|
||||
- [Delete List (deleteList)](api_methods/DeleteList.md)
|
||||
- [Get Lists (getLists)](api_methods/GetLists.md)
|
||||
- [Get Subscriber (getSubscriber)](api_methods/GetSubscriber.md)
|
||||
- [Get Subscribers (getSubscribers)](api_methods/GetSubscribers.md)
|
||||
- [Get Subscribers Count (getSubscribersCount)](api_methods/GetSubscribersCount.md)
|
||||
- [Get Subscriber Fields (getSubscriberFields)](api_methods/GetSubscriberFields.md)
|
||||
- [Is Setup Complete (isSetupComplete)](api_methods/IsSetupComplete.md)
|
||||
- [Subscribe to List (subscribeToList)](api_methods/SubscribeToList.md)
|
||||
- [Subscribe to Lists (subscribeToLists)](api_methods/SubscribeToLists.md)
|
||||
- [Unsubscribe globally](api_methods/UnsubscribeGlobally.md)
|
||||
- [Unsubscribe from List (unsubscribeFromList)](api_methods/UnsubscribeFromList.md)
|
||||
- [Unsubscribe from Lists (unsubscribeFromLists)](api_methods/UnsubscribeFromLists.md)
|
||||
- [Update List (updateList)](api_methods/UpdateList.md)
|
||||
* [Add List (addList)](api_methods/AddList.md)
|
||||
* [Add Subscriber (addSubscriber)](api_methods/AddSubscriber.md)
|
||||
* [Add Subscriber Field (addSubscriberField)](api_methods/AddSubscriberField.md)
|
||||
* [Get Lists (getLists)](api_methods/GetLists.md)
|
||||
* [Get Subscriber (getSubscriber)](api_methods/GetSubscriber.md)
|
||||
* [Get Subscriber Fields (getSubscriberFields)](api_methods/GetSubscriberFields.md)
|
||||
* [Is Setup Complete (isSetupComplete)](api_methods/IsSetupComplete.md)
|
||||
* [Subscribe to List (subscribeToList)](api_methods/SubscribeToList.md)
|
||||
* [Subscribe to List (subscribeToLists)](api_methods/SubscribeToLists.md)
|
||||
* [Unsubscribe from List (unsubscribeFromList)](api_methods/UnsubscribeFromList.md)
|
||||
* [Unsubscribe from Lists (unsubscribeFromLists)](api_methods/UnsubscribeFromLists.md)
|
||||
|
||||
### Usage examples
|
||||
|
||||
You can check some basic examples [here](UsageExamples.md).
|
||||
|
@ -1,18 +1,16 @@
|
||||
[back to readme](Readme.md)
|
||||
|
||||
# Usage Examples
|
||||
|
||||
Common usage is a rendering of a subscription form and processing it.
|
||||
|
||||
## Fetching data for a subscription form
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
if (class_exists(\MailPoet\API\API::class)) {
|
||||
// Get MailPoet API instance
|
||||
$mailpoet_api = \MailPoet\API\API::MP('v1');
|
||||
// Get available list so that a subscriber can choose in which to subscribe
|
||||
// Get available list so that a subscriber can choose in which to subscribe
|
||||
$lists = $mailpoet_api->getLists();
|
||||
// Get subscriber fields to know what fields can be rendered within a form
|
||||
$subscriber_form_fields = $mailpoet_api->getSubscriberFields();
|
||||
@ -20,14 +18,13 @@ if (class_exists(\MailPoet\API\API::class)) {
|
||||
```
|
||||
|
||||
## Processing a subscription form
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
if (class_exists(\MailPoet\API\API::class)) {
|
||||
// Get MailPoet API instance
|
||||
$mailpoet_api = \MailPoet\API\API::MP('v1');
|
||||
|
||||
|
||||
// Fill subscribed data from $_POST (for simplicity it expects that subscriber field ids are used as input names)
|
||||
$subscriber = [];
|
||||
$subscriber_form_fields = $mailpoet_api->getSubscriberFields();
|
||||
@ -53,7 +50,7 @@ if (class_exists(\MailPoet\API\API::class)) {
|
||||
$mailpoet_api->subscribeToLists($subscriber['email'], $list_ids);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$error_message = $e->getMessage();
|
||||
$error_message = $e->getMessage();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
[back to list](../Readme.md)
|
||||
|
||||
# Add List
|
||||
# Add Subscriber
|
||||
|
||||
## `array addList(array $list)`
|
||||
|
||||
@ -9,27 +9,26 @@ In MailPoet, subscribers are organized into lists. This method provides function
|
||||
It returns the new list. See [Get Lists](GetLists.md) for a list data structure description.
|
||||
|
||||
## Arguments
|
||||
|
||||
### `$list` (required)
|
||||
|
||||
An associative array which contains list data.
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ---------------------- | ------------ | --------- | -------------------------- |
|
||||
| name (required) | string | 90 chars | A name of the list. |
|
||||
| description (optional) | string\|null | 250 chars | A description of the list. |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| name (required) | string | 90 chars | A name of the list. |
|
||||
| description (optional) | string\|null| 250 chars | A description of the list. |
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------------------- |
|
||||
| 14 | Missing list name |
|
||||
| 15 | Trying to create a list that already exists |
|
||||
| 16 | The list couldn’t be created in the database |
|
||||
| Code | Description |
|
||||
| --- | --- |
|
||||
| 14 | Missing list name |
|
||||
| 15 | Trying to create a list that already exists |
|
||||
| 16 | The list couldn’t be created in the database |
|
||||
|
@ -8,9 +8,9 @@ This method allows a subscriber to be created, adds them into lists, and handles
|
||||
|
||||
If sign-up confirmation (double opt-in) is enabled in the MailPoet settings a subscriber is created with status `unconfirmed` otherwise the status is set to `subscribed`.
|
||||
|
||||
- _A confirmation email_ is an email which is sent to a subscriber so that they can confirm his subscription. It is sent only if sign-up confirmation is enabled in the MailPoet settings.
|
||||
- _A welcome email_ is an automatic email which is sent to a new subscriber. This email is scheduled only if sign-up confirmation is disabled and a welcome email is configured for some of given lists. In case of required sign-up confirmation, it is scheduled later after a subscriber confirms the subscription.
|
||||
- _An admin notification email_ is sent to the site admin to inform them about a new subscription. It is sent only if the notification feature is enabled in the MailPoet setting.
|
||||
- *A confirmation email* is an email which is sent to a subscriber so that they can confirm his subscription. It is sent only if sign-up confirmation is enabled in the MailPoet settings.
|
||||
- *A welcome email* is an automatic email which is sent to a new subscriber. This email is scheduled only if sign-up confirmation is disabled and a welcome email is configured for some of given lists. In case of required sign-up confirmation, it is scheduled later after a subscriber confirms the subscription.
|
||||
- *An admin notification email* is sent to the site admin to inform them about a new subscription. It is sent only if the notification feature is enabled in the MailPoet setting.
|
||||
|
||||
All these emails can be disabled using `$options`.
|
||||
|
||||
@ -21,33 +21,30 @@ There might be other `\Exceptions` because of some invalid input data such a inv
|
||||
It returns a new subscriber. See [Get Subscriber](GetSubscriber.md) for a subscriber data structure.
|
||||
|
||||
## Arguments
|
||||
|
||||
### `$subscriber` (required)
|
||||
|
||||
An associative array containing subscriber data which contains default properties (email, first_name, last_name) and custom subscriber fields which were defined in MailPoet.
|
||||
It has to contain an email and all required custom fields. To get defined custom fields see [Get Subscriber Fields](GetSubscriberFields.md)
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| -------------------------- | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| email (required) | string | 150 chars | a valid email address |
|
||||
| first_name (optional) | string/null | 255 chars | Fist name of the subscriber. |
|
||||
| last_name (optional) | string/null | 255 chars | Last name of the subscriber. |
|
||||
| cf\_\* (optional/required) | string/boolean/null | 65K chars | A custom field (see [Get Subscriber Fields](GetSubscriberFields.md)). <br> If a custom field is a checkbox, send truthy or falsy value (`true`/`false, `1`/`0`or`"1"`\`"0"`). |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| email (required) | string | 150 chars | a valid email address |
|
||||
| first_name (optional) | string/null | 255 chars | Fist name of the subscriber. |
|
||||
| last_name (optional) | string/null | 255 chars | Last name of the subscriber. |
|
||||
| cf_* (optional/required) | string/boolean/null | 65K chars | A custom field (see [Get Subscriber Fields](GetSubscriberFields.md)). <br> If a custom field is a checkbox, send truthy or falsy value (`true`/`false, `1`/`0` or `"1"`\`"0"`). |
|
||||
|
||||
### `$list_ids` (optional)
|
||||
|
||||
An array containing list ids into which subscriber will be added.
|
||||
In case that the list is empty a subscriber will be created; but sending a confirmation email, notification email and scheduling welcome email will be skipped.
|
||||
|
||||
### `$options` (optional)
|
||||
|
||||
All options are optional. If omitted a default value is used.
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ---------------------------- | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| send_confirmation_email | boolean | true | Can be used to disable a confirmation email. Otherwise, a confirmation email is sent as described above. It is strongly recommended to keep this option set to `true` so that MailPoet settings for sign-up confirmation are respected. Turning it to `false` might lead that subscriber to be added as `unconfirmed`. |
|
||||
| schedule_welcome_email | boolean | true | Can be used to disable a welcome email. Otherwise, a welcome email is scheduled as described above. |
|
||||
| skip_subscriber_notification | boolean | false | Can be used to disable an admin notification email. Otherwise, an admin notification email is sent as described above. |
|
||||
| Option | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| send_confirmation_email | boolean | true | Can be used to disable a confirmation email. Otherwise, a confirmation email is sent as described above. It is strongly recommended to keep this option set to `true` so that MailPoet settings for sign-up confirmation are respected. Turning it to `false` might lead that subscriber to be added as `unconfirmed`. |
|
||||
| schedule_welcome_email | boolean | true | Can be used to disable a welcome email. Otherwise, a welcome email is scheduled as described above.|
|
||||
| skip_subscriber_notification | boolean | false | Can be used to disable an admin notification email. Otherwise, an admin notification email is sent as described above.|
|
||||
|
||||
## Error handling
|
||||
|
||||
@ -58,9 +55,9 @@ An exception of base class `\Exception` can be thrown when something unexpected
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------------------------- |
|
||||
| 11 | Missing email address |
|
||||
| 12 | Trying to create a subscriber that already exists |
|
||||
| 13 | The subscriber couldn’t be created in the database |
|
||||
| 17 | Welcome email failed to send |
|
||||
| Code | Description |
|
||||
| --- | --- |
|
||||
| 11 | Missing email address |
|
||||
| 12 | Trying to create a subscriber that already exists |
|
||||
| 13 | The subscriber couldn’t be created in the database |
|
||||
| 17 | Welcome email failed to send |
|
||||
|
@ -11,77 +11,77 @@ See [Subscriber Fields for more details](GetSubscriberFields.md)
|
||||
|
||||
### `$data` (required)
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------- |
|
||||
| name (required) | string | 90 chars | Human readable name. Intended to be used, as an example, as a label for form input. |
|
||||
| type (required) | string | - | Type of the field. Possible values are: `text`, `date`, `textarea`, `radio`, `checkbox`, `select` |
|
||||
| params (optional) | array | - | Contains various information, see examples below. |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| name (required) | string | 90 chars | Human readable name. Intended to be used, as an example, as a label for form input. |
|
||||
| type (required) | string | - | Type of the field. Possible values are: `text`, `date`, `textarea`, `radio`, `checkbox`, `select` |
|
||||
| params (optional) | array | - | Contains various information, see examples below. |
|
||||
|
||||
### `$params`
|
||||
|
||||
Params array differs for each type.
|
||||
The common properties for all types:
|
||||
Params array differs for each type.
|
||||
The common properties for all types:
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------- | ------ | ------------------------------------------------------------------------------------------- |
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| required | string | Indicates if the value must be provided for each subscriber. Possible values are: "1" or "" |
|
||||
| label | string | Label used for displaying the field to the end user. |
|
||||
| label | string | Label used for displaying the field to the end user. |
|
||||
|
||||
#### `$params` for text, textarea types
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------- | ------ | ------------------------------------------------------------------------------------------- |
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| validate | string | Can be used for validating input values. Possible values are: `number`, `alphanum`, `phone` |
|
||||
|
||||
#### `$params` for checkbox types
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------- | ----- | ------------------------------------------------------------ |
|
||||
| values | array | Same array as for radio type. Must contain exactly 1 element |
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| values | array | Same array as for radio type. Must contain exactly 1 element |
|
||||
|
||||
#### `$params` for radio, select types
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------- | ----- | --------------------------------------------------------------------------------------------------- |
|
||||
| values | array | Contains a list of options. Each element must contain a string `value` and can contain `is_checked` |
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| values | array | Contains a list of options. Each element must contain a string `value` and can contain `is_checked` |
|
||||
|
||||
#### `$params` for date type
|
||||
|
||||
| Property | Type | Description |
|
||||
| ----------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| date_type | string | Possible values are: Values: `year_month_day`, `year_month`, `month`, `day` |
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| date_type | string | Possible values are: Values: `year_month_day`, `year_month`, `month`, `day` |
|
||||
| date_format | string | Values: for year_month_day: `MM/DD/YYYY`, `DD/MM/YYYY`, `YYYY/MM/DD`, for year_month: `YYYY/MM`, `MM/YY`, for year: `YYYY`, for month: `MM` |
|
||||
|
||||
## Response
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ---------- | ------------ | -------- | ------------------------------------------------------------------------------------------------- |
|
||||
| id | string | 11 chars | Field Id |
|
||||
| name | string | 90 chars | Human readable name. Intended to be used, as an example, as a label for form input. |
|
||||
| type | string | - | Type of the field. Possible values are: `text`, `date`, `textarea`, `radio`, `checkbox`, `select` |
|
||||
| params | array | - | Contains various information, see examples below. |
|
||||
| created_at | string\|null | - | UTC time of creation in `Y-m-d H:i:s` format |
|
||||
| updated_at | string | - | UTC time of last update in `Y-m-d H:i:s` format |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| id | string | 11 chars |Field Id |
|
||||
| name | string | 90 chars | Human readable name. Intended to be used, as an example, as a label for form input. |
|
||||
| type | string | - | Type of the field. Possible values are: `text`, `date`, `textarea`, `radio`, `checkbox`, `select` |
|
||||
| params | array | - | Contains various information, see examples below. |
|
||||
| created_at | string\|null | - | UTC time of creation in `Y-m-d H:i:s` format |
|
||||
| updated_at | string | - | UTC time of last update in `Y-m-d H:i:s` format |
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------------------------------------------------------------- |
|
||||
| 1 | The subscriber couldn’t be created in the database |
|
||||
| 1001 | Missing a mandatory field in the `$data` argument |
|
||||
| 1002 | A mandatory field in the `$data` argument has wrong type |
|
||||
| 1003 | `$params` is not an array |
|
||||
| 1004 | Attempting to create a field with an unknown type |
|
||||
| 1005 | Incorrect validate parameter for text type |
|
||||
| Code | Description |
|
||||
| --- | --- |
|
||||
| 1 | The subscriber couldn’t be created in the database |
|
||||
| 1001 | Missing a mandatory field in the `$data` argument |
|
||||
| 1002 | A mandatory field in the `$data` argument has wrong type |
|
||||
| 1003 | `$params` is not an array |
|
||||
| 1004 | Attempting to create a field with an unknown type |
|
||||
| 1005 | Incorrect validate parameter for text type |
|
||||
| 1006 | Passing a `values` array for the checkbox type that has incorrect number of values |
|
||||
| 1007 | Incorrect `date_format` value |
|
||||
| 1008 | Incorrect `date_type` value |
|
||||
| 1009 | Missing `values` for select or radio types |
|
||||
| 1010 | Empty `value` for select or radio types |
|
||||
| 1007 | Incorrect `date_format` value |
|
||||
| 1008 | Incorrect `date_type` value |
|
||||
| 1009 | Missing `values` for select or radio types |
|
||||
| 1010 | Empty `value` for select or radio types |
|
||||
|
@ -1,27 +0,0 @@
|
||||
[back to list](../Readme.md)
|
||||
|
||||
# Delete List
|
||||
|
||||
## `bool deleteList(string $list_id)`
|
||||
|
||||
This method provides functionality for deleting a list that is of the type 'default'.
|
||||
|
||||
It returns a boolean value.
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | --------------------------------------------------------------- |
|
||||
| 5 | List does not exist |
|
||||
| 18 | List id is empty |
|
||||
| 20 | List cannot be deleted because it’s used for an automatic email |
|
||||
| 21 | List cannot be deleted because it’s used for a form |
|
||||
| 22 | The list couldn’t be deleted from the database |
|
||||
| 23 | Only lists of the type 'default' can be deleted |
|
@ -8,18 +8,17 @@ In MailPoet, subscribers are organized into lists. This method returns an array
|
||||
|
||||
### A list data structure
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ----------- | ------------ | --------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| id | string | 11 chars | Id of the list |
|
||||
| name | string | 90 chars | Name of the list |
|
||||
| type | string | - | Type of the list. Currently, there is only one supported value: `default` |
|
||||
| description | string | 250 chars | Description of the list |
|
||||
| created_at | string\|null | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||
| deleted_at | string\|null | - | This property is not null only when the list is in the trash. It contains UTC time in 'Y-m-d H:i:s' format. |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| id | string | 11 chars | Id of the list |
|
||||
| name | string | 90 chars | Name of the list |
|
||||
| type | string | - | Type of the list. Currently, there is only one supported value: `default` |
|
||||
| description | string | 250 chars | Description of the list |
|
||||
| created_at | string\|null | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||
| deleted_at | string\|null | - | This property is not null only when the list is in the trash. It contains UTC time in 'Y-m-d H:i:s' format. |
|
||||
|
||||
### Response Example
|
||||
|
||||
```php
|
||||
<?php
|
||||
[
|
||||
|
@ -7,62 +7,45 @@
|
||||
This method throws an `\Exception` in the event a subscriber with a given email address doesn’t exist.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Description |
|
||||
| ----------------- | ------ | --------------------- |
|
||||
| Argument | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| $subscriber_email | string | a valid email address |
|
||||
|
||||
## A subscriber data structure
|
||||
|
||||
### Subscriber
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ------------------------ | ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| id | string | 11 chars | Id of the subscriber |
|
||||
| wp_user_id | string\|null | 20 chars | Id of a WordPress user associated with the subscriber |
|
||||
| is_woocommerce_user | string | - | A flag telling whether the user is also a WooCommerce customer. Possible values are: `1`, `0` |
|
||||
| first_name | string | 255 chars | Fist name of the subscriber. |
|
||||
| last_name | string | 255 chars | Last name of the subscriber. |
|
||||
| email | string | 150 chars | Email address of the subscriber. |
|
||||
| status | string | - | Status of the subscriber. Possible values are: `unconfirmed`, `subscribed`, `unsubscribed`, `bounced`, `inactive` |
|
||||
| subscribed_ip | string\|null | 45 chars | An IP address used for subscription. |
|
||||
| confirmed_ip | string\|null | 45 chars | An IP address used for confirmation. |
|
||||
| confirmed_at | string\|null | - | UTC time of subscription confirmation in 'Y-m-d H:i:s' format |
|
||||
| created_at | string\|null | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||
| deleted_at | string\|null | - | This property in not null in case that list is in trash and contains UTC time in 'Y-m-d H:i:s' format. |
|
||||
| last_subscribed_at | string\|null | - | UTC time of last confirmed subscription in 'Y-m-d H:i:s' format. |
|
||||
| unconfirmed_data | string\|null | 65K chars | May contain serialized subscriber data in case when there are pending changes waiting for a confirmation from a subscriber |
|
||||
| source | string\|null | - | Possible values: `form`,`imported`,`administrator`,`api`,`wordpress_user`,`woocommerce_user`,`woocommerce_checkout`,`unknown`) |
|
||||
| count_confirmations | string | 11 chars | Counter for confirmation emails |
|
||||
| subscriptions | array | - | List of subcriber subscriptions |
|
||||
| tags | array | - | List of subcriber tags |
|
||||
| cf\_{custom_field['id']} | string | 65K chars | A custom subscriber field value (see [Get Subscriber Fields](GetSubscriberFields.md) |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| id | string | 11 chars | Id of the subscriber |
|
||||
| wp_user_id | string\|null | 20 chars | Id of a WordPress user associated with the subscriber |
|
||||
| is_woocommerce_user | string | - | A flag telling whether the user is also a WooCommerce customer. Possible values are: `1`, `0` |
|
||||
| first_name | string | 255 chars | Fist name of the subscriber. |
|
||||
| last_name | string | 255 chars | Last name of the subscriber. |
|
||||
| email | string | 150 chars | Email address of the subscriber. |
|
||||
| status | string | - | Status of the subscriber. Possible values are: `unconfirmed`, `subscribed`, `unsubscribed`, `bounced`, `inactive` |
|
||||
| subscribed_ip | string\|null | 45 chars | An IP address used for subscription. |
|
||||
| confirmed_ip | string\|null | 45 chars | An IP address used for confirmation. |
|
||||
| confirmed_at | string\|null | - | UTC time of subscription confirmation in 'Y-m-d H:i:s' format |
|
||||
| created_at | string\|null | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||
| deleted_at | string\|null | - | This property in not null in case that list is in trash and contains UTC time in 'Y-m-d H:i:s' format. |
|
||||
| unconfirmed_data | string\|null | 65K chars | May contain serialized subscriber data in case when there are pending changes waiting for a confirmation from a subscriber |
|
||||
| source | string\|null | - | Possible values: `form`,`imported`,`administrator`,`api`,`wordpress_user`,`woocommerce_user`,`woocommerce_checkout`,`unknown`)
|
||||
| count_confirmations | string | 11 chars | Counter for confirmation emails |
|
||||
| subscriptions | array | - | List of subcriber subscriptions |
|
||||
| cf_{custom_field['id']}| string | 65K chars | A custom subscriber field value (see [Get Subscriber Fields](GetSubscriberFields.md)|
|
||||
|
||||
### Subscriber's subscription
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ------------- | ------ | -------- | ------------------------------------------------------------------------------------ |
|
||||
| id | string | 11 chars | Id of relation |
|
||||
| subscriber_id | string | 11 chars | Id of subscriber |
|
||||
| segment_id | string | 11 chars | Id of a list |
|
||||
| status | string | - | Status of a subscription for the list. Possible values: `subscribed`, `unsubscribed` |
|
||||
| created_at | string | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||
|
||||
### Subscriber's tag
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------------------- |
|
||||
| id | string | 11 chars | Id of relation |
|
||||
| subscriber_id | string | 11 chars | Id of subscriber |
|
||||
| tag_id | string | 11 chars | Id of a list |
|
||||
| name | string | - | Name of a tag |
|
||||
| created_at | string | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| id | string | 11 chars | Id of relation |
|
||||
| subscriber_id | string | 11 chars | Id of subscriber |
|
||||
| segment_id | string | 11 chars | Id of a list |
|
||||
| status | string | - | Status of a subscription for the list. Possible values: `subscribed`, `unsubscribed` |
|
||||
| created_at | string | - | UTC time of creation in 'Y-m-d H:i:s' format |
|
||||
| updated_at | string | - | UTC time of last update in 'Y-m-d H:i:s' format |
|
||||
|
||||
### Response Example
|
||||
|
||||
```php
|
||||
<?php
|
||||
[
|
||||
@ -100,24 +83,6 @@ This method throws an `\Exception` in the event a subscriber with a given email
|
||||
'updated_at' => '2019-05-14 08:43:08',
|
||||
],
|
||||
],
|
||||
'tags' => [
|
||||
0 => [
|
||||
'id' => '2',
|
||||
'subscriber_id' => '10',
|
||||
'tag_id' => '1',
|
||||
'name' => 'Alpha',
|
||||
'created_at' => '2019-05-17 05:24:37',
|
||||
'updated_at' => '2019-05-17 05:24:37',
|
||||
],
|
||||
1 => [
|
||||
'id' => '4',
|
||||
'subscriber_id' => '10',
|
||||
'tag_id' => '5',
|
||||
'name' => 'Beta',
|
||||
'created_at' => '2020-03-07 15:21:37',
|
||||
'updated_at' => '2020-03-07 15:21:37',
|
||||
],
|
||||
],
|
||||
'cf_1' => 'US',
|
||||
'cf_2' => 'New York',
|
||||
];
|
||||
@ -125,13 +90,13 @@ This method throws an `\Exception` in the event a subscriber with a given email
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------------------- |
|
||||
| 4 | Asking for a subscriber that does not exist. |
|
||||
| Code | Description |
|
||||
| --- | --- |
|
||||
| 4 | Asking for a subscriber that does not exist. |
|
||||
|
@ -11,15 +11,14 @@ See also [addSubscriberField function.](AddSubscriberField.md)
|
||||
|
||||
## Subscriber Field
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| -------- | ------ | -------- | ------------------------------------------------------------------------------------------------- |
|
||||
| id | string | 11 chars | Field Id |
|
||||
| name | string | 90 chars | Human readable name. Intended to be used, as an example, as a label for form input. |
|
||||
| type | string | - | Type of the field. Possible values are: `text`, `date`, `textarea`, `radio`, `checkbox`, `select` |
|
||||
| params | array | - | Contains various information, see examples below. |
|
||||
| Property | Type | Limits | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| id | string | 11 chars |Field Id |
|
||||
| name | string | 90 chars | Human readable name. Intended to be used, as an example, as a label for form input. |
|
||||
| type | string | - | Type of the field. Possible values are: `text`, `date`, `textarea`, `radio`, `checkbox`, `select` |
|
||||
| params | array | - | Contains various information, see examples below. |
|
||||
|
||||
## Response Example
|
||||
|
||||
```php
|
||||
<?php
|
||||
[
|
||||
|
@ -1,25 +0,0 @@
|
||||
[back to list](../Readme.md)
|
||||
|
||||
# Get Subscribers
|
||||
|
||||
## `array getSubscribers(array $filter = [], int $limit = 50, int $offset = 0)`
|
||||
|
||||
This method returns a list of subscribers. To see the subscriber data structure, please check [getSubscriber()](GetSubscriber.md) documentation.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| ------------------ | ----- | ------- | --------------------------------------- |
|
||||
| $filter (optional) | array | empty | Filters to retrieve subscribers |
|
||||
| $limit (optional) | int | 50 | The number of results that are returned |
|
||||
| $offset (optional) | int | 0 | From where to start returning data |
|
||||
|
||||
### Filter
|
||||
|
||||
Filter argument supports following array keys.
|
||||
|
||||
| Key | Type | Description |
|
||||
| ------------ | ------------ | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| status | string | Specific status of subscribers. One of values: `unconfirmed`, `subscribed`, `unsubscribed`, `bounced`, `inactive` |
|
||||
| listId | int | List id or dynamic segment id |
|
||||
| minUpdatedAt | DateTime\int | DateTime object or timestamp of the minimal last update of subscribers |
|
@ -1,17 +0,0 @@
|
||||
[back to list](../Readme.md)
|
||||
|
||||
# Get Subscribers Count
|
||||
|
||||
## `int getSubscribersCount(array $filter = [])`
|
||||
|
||||
This method returns the count of subscribers by a filter.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| ------------------ | ----- | ------- | -------------------------------------------- |
|
||||
| $filter (optional) | array | empty | Filters to retrieve the count of subscribers |
|
||||
|
||||
### Filter
|
||||
|
||||
To see supported filters, please check [getSubscribers()](GetSubscribers.md) documentation.
|
@ -6,50 +6,46 @@
|
||||
|
||||
This method allows adding an existing subscriber into lists and handles confirmation email and admin notification email sending.
|
||||
|
||||
- _A confirmation email_ is an email which is sent to a subscriber so they can confirm their subscription. It is sent only if sign-up confirmation is enabled in MailPoet settings and subscriber has not received any confirmation email yet.
|
||||
- _A welcome email_ is an automatic email which is sent to a new subscriber. This email is scheduled only if sign-up confirmation is disabled and some welcome email is configured for some of given lists.
|
||||
- _An admin notification email_ is sent to the site admin to inform them about a new subscription. It is sent only if the notification feature is enabled in the MailPoet setting.
|
||||
- *A confirmation email* is an email which is sent to a subscriber so they can confirm their subscription. It is sent only if sign-up confirmation is enabled in MailPoet settings and subscriber has not received any confirmation email yet.
|
||||
- *A welcome email* is an automatic email which is sent to a new subscriber. This email is scheduled only if sign-up confirmation is disabled and some welcome email is configured for some of given lists.
|
||||
- *An admin notification email* is sent to the site admin to inform them about a new subscription. It is sent only if the notification feature is enabled in the MailPoet setting.
|
||||
|
||||
All these emails can be disabled using `$options`.
|
||||
|
||||
It returns a subscriber. See [Get Subscriber](GetSubscriber.md) for a subscriber data structure.
|
||||
|
||||
## Arguments
|
||||
|
||||
### string `$subscriber_id` (required)
|
||||
|
||||
An id or an email address. An `\Exception` is thrown when the value doesn't match any subscriber.
|
||||
|
||||
### array `$list_ids` (required)
|
||||
|
||||
An array of list ids. An `\Exception` is thrown if any of list ids are invalid. In such a case the subscriber isn't added to any list.
|
||||
|
||||
### array `$options` (optional)
|
||||
|
||||
All options are optional. If omitted, a default value is used.
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ---------------------------- | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| send_confirmation_email | boolean | true | Can be used to disable confirmation email. Otherwise, a confirmation email is sent as described above. |
|
||||
| schedule_welcome_email | boolean | true | Can be used to disable welcome email. Otherwise, a welcome email is scheduled as described above. |
|
||||
| skip_subscriber_notification | boolean | false | Can be used to disable an admin notification email. Otherwise, an admin notification email is sent as described above. |
|
||||
| Option | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| send_confirmation_email | boolean | true | Can be used to disable confirmation email. Otherwise, a confirmation email is sent as described above.|
|
||||
| schedule_welcome_email | boolean | true | Can be used to disable welcome email. Otherwise, a welcome email is scheduled as described above.|
|
||||
| skip_subscriber_notification | boolean | false | Can be used to disable an admin notification email. Otherwise, an admin notification email is sent as described above.|
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------------------------------- |
|
||||
| 3 | No lists provided |
|
||||
| 4 | Invalid subscriber that does not exist |
|
||||
| 5 | Invalid list that does not exist |
|
||||
| 6 | Trying to subscribe to a WordPress Users list |
|
||||
| 7 | Trying to subscribe to a WooCommerce Customers list |
|
||||
| 8 | Trying to subscribe to a list that doesn’t support that |
|
||||
| 10 | Confirmation email failed to send |
|
||||
| 17 | Welcome email failed to send |
|
||||
| Code | Description |
|
||||
| --- | --- |
|
||||
| 3 | No lists provided |
|
||||
| 4 | Invalid subscriber that does not exist |
|
||||
| 5 | Invalid list that does not exist |
|
||||
| 6 | Trying to subscribe to a WordPress Users list |
|
||||
| 7 | Trying to subscribe to a WooCommerce Customers list |
|
||||
| 8 | Trying to subscribe to a list that doesn’t support that |
|
||||
| 10 | Confirmation email failed to send |
|
||||
| 17 | Welcome email failed to send |
|
||||
|
@ -9,29 +9,26 @@ This method removes a subscriber from given lists.
|
||||
It returns a subscriber. See [Get Subscriber](GetSubscriber.md) for a subscriber data structure.
|
||||
|
||||
## Arguments
|
||||
|
||||
### string `$subscriber_id` (required)
|
||||
|
||||
An id or email of an existing subscriber. An `\Exception` is thrown when an id or email doesn't match any subscriber.
|
||||
|
||||
### array `$list_ids` (required)
|
||||
|
||||
An array of list ids. An `\Exception` is thrown if any of list ids are invalid. In such a case the subscriber remains subscribed to all lists.
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | --------------------------------------------------- |
|
||||
| 3 | No lists provided |
|
||||
| 4 | Invalid subscriber that does not exist |
|
||||
| 5 | Invalid list that does not exist |
|
||||
| 6 | Trying to subscribe to a WordPress Users list |
|
||||
| 7 | Trying to subscribe to a WooCommerce Customers list |
|
||||
| 10 | Confirmation email failed to send |
|
||||
| Code | Description |
|
||||
| --- | --- |
|
||||
| 3 | No lists provided |
|
||||
| 4 | Invalid subscriber that does not exist |
|
||||
| 5 | Invalid list that does not exist |
|
||||
| 6 | Trying to subscribe to a WordPress Users list |
|
||||
| 7 | Trying to subscribe to a WooCommerce Customers list |
|
||||
| 10 | Confirmation email failed to send |
|
||||
|
@ -1,29 +0,0 @@
|
||||
[back to list](../Readme.md)
|
||||
|
||||
# Unsubscribe from all lists and change subscriber status
|
||||
|
||||
## `array unsubscribe(string $subscriber_id)`
|
||||
|
||||
This method removes a subscriber from all lists and updates its status to 'unsubscribed'.
|
||||
|
||||
It returns a subscriber. See [Get Subscriber](GetSubscriber.md) for returned data structure.
|
||||
|
||||
## Arguments
|
||||
|
||||
### string `$subscriber_id` (required)
|
||||
|
||||
An id or email of an existing subscriber. An `\Exception` is thrown when an id or email doesn't match any subscriber.
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------------------- |
|
||||
| 4 | Invalid subscriber that does not exist |
|
||||
| 24 | Subscriber already has 'unsubscribed' status |
|
@ -1,39 +0,0 @@
|
||||
[back to list](../Readme.md)
|
||||
|
||||
# Update List
|
||||
|
||||
## `array updateList(array $list)`
|
||||
|
||||
This method provides functionality for updating a list name or description. Only lists of type 'default' are supported.
|
||||
|
||||
It returns the updated list. See [Get Lists](GetLists.md) for a list data structure description.
|
||||
|
||||
## Arguments
|
||||
|
||||
### `$list` (required)
|
||||
|
||||
An associative array which contains list data.
|
||||
|
||||
| Property | Type | Limits | Description |
|
||||
| ---------------------- | ------------ | --------- | -------------------------------------------------------------------------- |
|
||||
| id (required) | string | 11 chars | A id of the list. |
|
||||
| name (required) | string | 90 chars | A name of the list. |
|
||||
| description (optional) | string\|null | 250 chars | A description of the list. This will reset the list description when empty |
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------------------- |
|
||||
| 5 | The list was not found by id |
|
||||
| 14 | Missing list name |
|
||||
| 15 | Trying to use a list name that is already used |
|
||||
| 18 | Missing list id |
|
||||
| 19 | The list couldn’t be updated in the database |
|
||||
| 23 | Only lists of the type 'default' can be updated |
|
@ -1,33 +0,0 @@
|
||||
[back to list](../Readme.md)
|
||||
|
||||
# Update Subscriber
|
||||
|
||||
## `array updateSubscriber($subscriberIdOrEmail, array $subscriber): array`
|
||||
|
||||
This method allows a subscriber to be updated.
|
||||
The argument `$subscriber` is similar to [Add Subscriber](AddSubscriber.md) method, but the subscriber is updated instead of created.
|
||||
|
||||
It returns the updated subscriber. See [Get Subscriber](GetSubscriber.md) for a subscriber data structure.
|
||||
|
||||
If the subscriber is a WordPress user, the method does not allow updating `email`, `first_name` and `last_name`. It needs to be updated in the `wp_users` and MailPoet will synchronise the new values.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Description |
|
||||
| -------------------- | ------------- | ----------------------------------------- |
|
||||
| $subscriberIdOrEmail | string or int | An id or email of an existing subscriber. |
|
||||
| $subscriber | array | Subscriber data that will be updated |
|
||||
|
||||
## Error handling
|
||||
|
||||
All expected errors from the API are exceptions of class `\MailPoet\API\MP\v1\APIException`.
|
||||
Code of the exception is populated to distinguish between different errors.
|
||||
|
||||
An exception of base class `\Exception` can be thrown when something unexpected happens.
|
||||
|
||||
Codes description:
|
||||
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------------------------- |
|
||||
| 4 | Updating a subscriber that does not exist. |
|
||||
| 13 | The subscriber couldn’t be updated in the database |
|
@ -1,3 +1,5 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# for M1 Macs
|
||||
db:
|
||||
@ -20,16 +22,16 @@ volumes:
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=host.docker.internal,nolock
|
||||
device: ':/System/Volumes/Data${PWD}/wordpress'
|
||||
device: ":/System/Volumes/Data${PWD}/wordpress"
|
||||
nfs-mailpoet:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=host.docker.internal,nolock
|
||||
device: ':/System/Volumes/Data${PWD}/mailpoet'
|
||||
device: ":/System/Volumes/Data${PWD}/mailpoet"
|
||||
nfs-mailpoet-premium:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=host.docker.internal,nolock
|
||||
device: ':/System/Volumes/Data${PWD}/mailpoet-premium'
|
||||
device: ":/System/Volumes/Data${PWD}/mailpoet-premium"
|
||||
|
@ -1,3 +1,5 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
dashboard:
|
||||
container_name: mp-dashboard
|
||||
@ -13,7 +15,6 @@ services:
|
||||
volumes:
|
||||
- my-datavolume:/var/lib/mysql
|
||||
- ./dev/database/create_test_db.sh:/docker-entrypoint-initdb.d/10-create_test_db.sh
|
||||
command: --sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,ANSI,ONLY_FULL_GROUP_BY
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: somewordpress
|
||||
MYSQL_DATABASE: wordpress
|
||||
@ -25,12 +26,13 @@ services:
|
||||
container_name: mp-wp
|
||||
build:
|
||||
context: .
|
||||
dockerfile: dev/php82/Dockerfile
|
||||
dockerfile: dev/php80/Dockerfile
|
||||
args:
|
||||
UID: ${UID:-1000}
|
||||
GID: ${GID:-1000}
|
||||
ports:
|
||||
- '8002:80'
|
||||
- "8002:80"
|
||||
- "8083:8083" # Storybook port number, see package.json
|
||||
depends_on:
|
||||
- db
|
||||
- smtp
|
||||
@ -41,35 +43,27 @@ services:
|
||||
WORDPRESS_DB_HOST: db:3306
|
||||
WORDPRESS_DB_USER: wordpress
|
||||
WORDPRESS_DB_PASSWORD: wordpress
|
||||
PHP_IDE_CONFIG: 'serverName=Mailpoet'
|
||||
COMPOSER_HOME: '/tmp/.composer'
|
||||
NPM_CONFIG_CACHE: '/tmp/.npm'
|
||||
XDG_CACHE_HOME: '/tmp/.cache'
|
||||
PHP_IDE_CONFIG: "serverName=Mailpoet"
|
||||
COMPOSER_HOME: "/tmp/.composer"
|
||||
NPM_CONFIG_CACHE: "/tmp/.npm"
|
||||
MAILPOET_DEV_SITE: 1
|
||||
volumes:
|
||||
- './wordpress:/var/www/html'
|
||||
- './tsconfig.base.json:/var/www/html/wp-content/plugins/tsconfig.base.json:ro'
|
||||
- './.npmrc:/var/www/html/wp-content/plugins/.npmrc'
|
||||
- './package.json:/var/www/html/wp-content/plugins/package.json'
|
||||
- './pnpm-lock.yaml:/var/www/html/wp-content/plugins/pnpm-lock.yaml'
|
||||
- './pnpm-workspace.yaml:/var/www/html/wp-content/plugins/pnpm-workspace.yaml'
|
||||
- './patches:/var/www/html/wp-content/plugins/patches'
|
||||
- './tests_env:/var/www/html/wp-content/plugins/tests_env'
|
||||
- './mailpoet:/var/www/html/wp-content/plugins/mailpoet'
|
||||
- './mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium'
|
||||
- './packages:/var/www/html/wp-content/plugins/packages'
|
||||
- './templates:/var/www/templates'
|
||||
- "./wordpress:/var/www/html"
|
||||
- "./eslint-config:/var/www/html/wp-content/plugins/eslint-config"
|
||||
- "./mailpoet:/var/www/html/wp-content/plugins/mailpoet"
|
||||
- "./mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium"
|
||||
- "./templates:/var/www/templates"
|
||||
|
||||
test_wordpress:
|
||||
container_name: mp-test-wp
|
||||
build:
|
||||
context: .
|
||||
dockerfile: dev/php81/Dockerfile
|
||||
dockerfile: dev/php80/Dockerfile
|
||||
args:
|
||||
UID: ${UID:-1000}
|
||||
GID: ${GID:-1000}
|
||||
ports:
|
||||
- '8003:80'
|
||||
- "8003:80"
|
||||
depends_on:
|
||||
- db
|
||||
- smtp
|
||||
@ -79,11 +73,11 @@ services:
|
||||
WORDPRESS_DB_HOST: db:3306
|
||||
WORDPRESS_DB_USER: wordpress
|
||||
WORDPRESS_DB_PASSWORD: wordpress
|
||||
PHP_IDE_CONFIG: 'serverName=Mailpoet'
|
||||
PHP_IDE_CONFIG: "serverName=Mailpoet"
|
||||
volumes:
|
||||
- './mailpoet:/var/www/html/wp-content/plugins/mailpoet'
|
||||
- './mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium'
|
||||
- './packages:/var/www/html/wp-content/plugins/packages'
|
||||
- "./eslint-config:/var/www/html/wp-content/plugins/eslint-config"
|
||||
- "./mailpoet:/var/www/html/wp-content/plugins/mailpoet"
|
||||
- "./mailpoet-premium:/var/www/html/wp-content/plugins/mailpoet-premium"
|
||||
|
||||
smtp:
|
||||
container_name: mp-mailhog
|
||||
@ -93,9 +87,9 @@ services:
|
||||
MH_STORAGE: maildir
|
||||
MH_MAILDIR_PATH: /output
|
||||
volumes:
|
||||
- './dev/data/mailhog:/output'
|
||||
- "./dev/data/mailhog:/output"
|
||||
ports:
|
||||
- '8082:8025'
|
||||
- "8082:8025"
|
||||
|
||||
adminer:
|
||||
container_name: mp-adminer
|
||||
@ -103,9 +97,9 @@ services:
|
||||
depends_on:
|
||||
- db
|
||||
ports:
|
||||
- '8081:8080'
|
||||
- "8081:8080"
|
||||
volumes:
|
||||
- './dev/php.ini:/usr/local/etc/php/conf.d/custom.ini'
|
||||
- "./dev/php.ini:/usr/local/etc/php/conf.d/custom.ini"
|
||||
|
||||
volumes:
|
||||
my-datavolume:
|
||||
|
33
eslint-config/.eslintrc-premium.json
Normal file
33
eslint-config/.eslintrc-premium.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"extends": "airbnb",
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
"react-hooks"
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": "webpack"
|
||||
},
|
||||
"rules": {
|
||||
"class-methods-use-this": 0,
|
||||
// React hooks rules
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
// Exceptions
|
||||
"arrow-parens": ["error", "always"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"import/extensions": 0, // we wouldn't be able to import jQuery without this line
|
||||
"jsx-a11y/anchor-is-valid": [ "error", {
|
||||
"components": [ "Link" ],
|
||||
"specialLink": [ "to" ]
|
||||
}]
|
||||
}
|
||||
}
|
72
eslint-config/.eslintrc-premium.ts.json
Normal file
72
eslint-config/.eslintrc-premium.ts.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking"
|
||||
],
|
||||
"env": {
|
||||
"amd": true,
|
||||
"browser": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"tsconfigRootDir": ".",
|
||||
"project": ["./tsconfig.json"],
|
||||
"ecmaVersion": 6,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
"react-hooks",
|
||||
"no-only-tests",
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": "webpack"
|
||||
},
|
||||
"rules": {
|
||||
"class-methods-use-this": 0,
|
||||
"no-use-before-define": "off", // disable the original rule, use only the typescript rule on the next line
|
||||
"@typescript-eslint/no-use-before-define": ["error"],
|
||||
// PropTypes
|
||||
"react/prop-types": 0,
|
||||
"react/jsx-props-no-spreading": 0,
|
||||
// Hooks
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
// Exceptions
|
||||
"camelcase": 0, //use the typescript version
|
||||
"no-shadow": 0, //use the typescript version
|
||||
"react/jsx-filename-extension": 0,
|
||||
"arrow-parens": ["error", "always"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"no-only-tests/no-only-tests": 2,
|
||||
"no-script-url": 0,
|
||||
"@typescript-eslint/no-unsafe-return": 0, // we need to disable it for wordpress select :(
|
||||
"@typescript-eslint/no-unsafe-member-access": 0, // we need to disable it for wordpress select :(
|
||||
"@typescript-eslint/no-unsafe-call": 0, // this needs to match the one defined for free plugin
|
||||
"@typescript-eslint/no-unsafe-assignment": 0, // this needs to match the one defined for free plugin
|
||||
"import/extensions": 0, // we wouldn't be able to import jQuery without this line
|
||||
"import/prefer-default-export": 0, // we want to stop using default exports and start using named exports
|
||||
"react/destructuring-assignment": 0, // that would be too many changes to fix this one
|
||||
"prefer-destructuring": 0, // that would be too many changes to fix this one
|
||||
"jsx-a11y/label-has-for": [2, {
|
||||
"required": {"some": ["nesting", "id"]} // some of our labels are hidden and we cannot nest those
|
||||
}],
|
||||
"jsx-a11y/anchor-is-valid": 0, // cannot fix this one, it would break wprdpress themes
|
||||
"jsx-a11y/label-has-associated-control": [ 2, {
|
||||
"either": "either" // control has to be either nested or associated via htmlFor
|
||||
}]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/_stories/*.tsx"],
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
17
eslint-config/.eslintrc.es5.json
Normal file
17
eslint-config/.eslintrc.es5.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "airbnb/legacy",
|
||||
"env": {
|
||||
"amd": true,
|
||||
"browser": true
|
||||
},
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"import/prefer-default-export": 0, // we want to stop using default exports and start using named exports
|
||||
"no-underscore-dangle": 0, // Backbone uses underscores, we cannot remove them
|
||||
"comma-dangle": ["error", "always-multiline"]
|
||||
}
|
||||
}
|
59
eslint-config/.eslintrc.es6.json
Normal file
59
eslint-config/.eslintrc.es6.json
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"extends": "airbnb",
|
||||
"env": {
|
||||
"amd": true,
|
||||
"browser": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
"react-hooks",
|
||||
"no-only-tests"
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": "webpack"
|
||||
},
|
||||
"rules": {
|
||||
// Hooks
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
// Exceptions
|
||||
"arrow-parens": ["error", "always"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"no-only-tests/no-only-tests": 2,
|
||||
"no-script-url": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"react/jsx-props-no-spreading": 0,
|
||||
"import/extensions": 0, // we wouldn't be able to import jQuery without this line
|
||||
"import/prefer-default-export": 0, // we want to stop using default exports and start using named exports
|
||||
"react/destructuring-assignment": 0, // that would be too many changes to fix this one
|
||||
"prefer-destructuring": 0, // that would be too many changes to fix this one
|
||||
"jsx-a11y/label-has-for": [2, {
|
||||
"required": {"some": ["nesting", "id"]} // some of our labels are hidden and we cannot nest those
|
||||
}],
|
||||
"jsx-a11y/anchor-is-valid": 0, // cannot fix this one, it would break wprdpress themes
|
||||
"jsx-a11y/label-has-associated-control": [ 2, {
|
||||
"either": "either" // control has to be either nested or associated via htmlFor
|
||||
}],
|
||||
"indent": ["error", 2, {// bug in babel eslint https://github.com/babel/babel-eslint/issues/681#issuecomment-451336031 we can remove this whole exception in the future when the bug is fixed
|
||||
"ignoredNodes": ["TemplateLiteral"],
|
||||
"SwitchCase": 1
|
||||
}],
|
||||
"template-curly-spacing": "off"// bug in babel eslint https://github.com/babel/babel-eslint/issues/681#issuecomment-623101005 we can remove this whole exception in the future when the bug is fixed
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.spec.js"],
|
||||
"rules": {
|
||||
"no-unused-expressions": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
20
eslint-config/.eslintrc.tests_newsletter_editor.json
Normal file
20
eslint-config/.eslintrc.tests_newsletter_editor.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "airbnb/legacy",
|
||||
"env": {
|
||||
"amd": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"no-only-tests/no-only-tests": 2,
|
||||
// Exceptions
|
||||
"func-names": 0,
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
// Temporary
|
||||
"no-underscore-dangle": 0
|
||||
},
|
||||
"plugins": ["no-only-tests"]
|
||||
}
|
392
eslint-config/.eslintrc.ts.json
Normal file
392
eslint-config/.eslintrc.ts.json
Normal file
@ -0,0 +1,392 @@
|
||||
{
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking"
|
||||
],
|
||||
"env": {
|
||||
"amd": true,
|
||||
"browser": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"tsconfigRootDir": ".",
|
||||
"project": ["./tsconfig.json"],
|
||||
"ecmaVersion": 6,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
"react-hooks",
|
||||
"no-only-tests",
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": "webpack",
|
||||
"import/core-modules": [
|
||||
"@woocommerce/blocks-checkout",
|
||||
"@woocommerce/settings",
|
||||
"@wordpress/a11y",
|
||||
"@wordpress/api-fetch",
|
||||
"@wordpress/block-editor",
|
||||
"@wordpress/compose",
|
||||
"@wordpress/data",
|
||||
"@wordpress/escape-html",
|
||||
"@wordpress/hooks",
|
||||
"@wordpress/keycodes",
|
||||
"@wordpress/url",
|
||||
"react"
|
||||
]
|
||||
},
|
||||
"rules": {
|
||||
"react/no-unstable-nested-components": [
|
||||
"error",
|
||||
{ "allowAsProps": true }
|
||||
],
|
||||
// PropTypes
|
||||
"react/prop-types": 0,
|
||||
"react/jsx-props-no-spreading": 0,
|
||||
"react/require-default-props": 0,
|
||||
// Hooks
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
// Exceptions
|
||||
"@typescript-eslint/no-explicit-any": "error", // make it an error instead of warning - we treat them the same, this is more visible
|
||||
"no-use-before-define": 0, //use the typescript version
|
||||
"camelcase": 0, //use the typescript version
|
||||
"no-shadow": 0, //use the typescript version
|
||||
"no-void": 0, // can conflict with @typescript-eslint/no-floating-promises
|
||||
"react/jsx-no-useless-fragment" : [
|
||||
"error",
|
||||
{
|
||||
"allowExpressions": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{ "selector": "classProperty", "format": [] },
|
||||
{ "selector": "typeProperty", "format": [] },
|
||||
{ "selector": "objectLiteralProperty", "format": [] },
|
||||
{ "selector": "variableLike", "format": ["UPPER_CASE", "camelCase", "PascalCase"] }
|
||||
],
|
||||
"react/jsx-filename-extension": 0,
|
||||
"arrow-parens": ["error", "always"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"no-only-tests/no-only-tests": 2,
|
||||
"class-methods-use-this": 0,
|
||||
"react/jsx-props-no-spreading": 0,
|
||||
"no-script-url": 0,
|
||||
"@typescript-eslint/no-unsafe-return": 0, // we need to disable it for wordpress select :(
|
||||
"@typescript-eslint/no-unsafe-member-access": 0, // this needs to be off until we have typed assignments :(
|
||||
"@typescript-eslint/no-unsafe-call": 0, // this needs to be off until we have typed assignments :(
|
||||
"@typescript-eslint/no-unsafe-assignment": 0, // this needs to be off until we have typed assignments :(
|
||||
"import/extensions": 0, // we wouldn't be able to import jQuery without this line
|
||||
"import/prefer-default-export": 0, // we want to stop using default exports and start using named exports
|
||||
"react/destructuring-assignment": 0, // that would be too many changes to fix this one
|
||||
"prefer-destructuring": 0, // that would be too many changes to fix this one
|
||||
"jsx-a11y/label-has-for": [2, {
|
||||
"required": {"some": ["nesting", "id"]} // some of our labels are hidden and we cannot nest those
|
||||
}],
|
||||
"jsx-a11y/anchor-is-valid": 0, // cannot fix this one, it would break wprdpress themes
|
||||
"jsx-a11y/label-has-associated-control": [ 2, {
|
||||
"either": "either" // control has to be either nested or associated via htmlFor
|
||||
}],
|
||||
"@typescript-eslint/explicit-module-boundary-types": "error"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/_stories/*.tsx"],
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }]
|
||||
}
|
||||
},
|
||||
{
|
||||
// this violation has been added by a formed employee and we don't know how that works any more, so ignore
|
||||
"files": [
|
||||
"assets/js/src/settings/pages/advanced/reinstall.tsx",
|
||||
"assets/js/src/settings/pages/advanced/recalculate_subscriber_score.tsx",
|
||||
"assets/js/src/settings/pages/key_activation/key_activation.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/activate_or_cancel.tsx",
|
||||
"assets/js/src/settings/pages/send_with/send_with_choice.tsx"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/await-thenable": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
// too many violations, skipping for now
|
||||
"files": [
|
||||
"assets/js/src/announcements/feature_announcement.tsx",
|
||||
"assets/js/src/announcements/with_feature_announcement.tsx",
|
||||
"assets/js/src/common/controls/call_api.ts",
|
||||
"assets/js/src/common/form/react_select/react_select.tsx",
|
||||
"assets/js/src/common/functions/is_email.ts",
|
||||
"assets/js/src/common/functions/t.ts",
|
||||
"assets/js/src/common/listings/newsletter_stats/stats.tsx",
|
||||
"assets/js/src/common/listings/newsletter_status.tsx",
|
||||
"assets/js/src/common/set_from_address_modal.tsx",
|
||||
"assets/js/src/common/tabs/routed_tabs.tsx",
|
||||
"assets/js/src/common/thumbnail.ts",
|
||||
"assets/js/src/form_editor/blocks/submit/edit.tsx",
|
||||
"assets/js/src/form_editor/components/close_button_settings.tsx",
|
||||
"assets/js/src/form_editor/components/font_family_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/below_pages.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/fixed_bar.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/other.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/popup.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/animation_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/below_posts_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/fixed_bar_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/other_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/placement_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/popup_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/settings_panels/slide_in_settings.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_placement_options/slide_in.tsx",
|
||||
"assets/js/src/form_editor/components/form_settings/form_settings.tsx",
|
||||
"assets/js/src/form_editor/components/fullscreen.tsx",
|
||||
"assets/js/src/form_editor/components/history_redo.tsx",
|
||||
"assets/js/src/form_editor/components/history_undo.tsx",
|
||||
"assets/js/src/form_editor/components/preview/preview.tsx",
|
||||
"assets/js/src/form_editor/components/sidebar/default_sidebar.tsx",
|
||||
"assets/js/src/form_editor/components/sidebar/placement_settings_sidebar.tsx",
|
||||
"assets/js/src/form_editor/components/sidebar/sidebar.tsx",
|
||||
"assets/js/src/form_editor/components/tutorial.tsx",
|
||||
"assets/js/src/form_editor/form_preview.ts",
|
||||
"assets/js/src/form_editor/hooks.tsx",
|
||||
"assets/js/src/form_editor/rich_text/font_selection_format.tsx",
|
||||
"assets/js/src/form_editor/store/actions.ts",
|
||||
"assets/js/src/form_editor/store/reducers/change_active_sidebar.ts",
|
||||
"assets/js/src/form_editor/store/reducers/history_record.ts",
|
||||
"assets/js/src/form_editor/store/reducers/toggle_form.ts",
|
||||
"assets/js/src/form_editor/store/reducers/toggle_fullscreen.ts",
|
||||
"assets/js/src/form_editor/store/reducers/tutorial_dismiss.ts",
|
||||
"assets/js/src/form_editor/templates/selection.tsx",
|
||||
"assets/js/src/form_editor/templates/store/actions.ts",
|
||||
"assets/js/src/form_editor/utils/link_suggestions.tsx",
|
||||
"assets/js/src/logs/list.tsx",
|
||||
"assets/js/src/newsletters/automatic_emails/events/event_options.tsx",
|
||||
"assets/js/src/newsletters/campaign_stats/newsletter_general_stats.tsx",
|
||||
"assets/js/src/newsletters/campaign_stats/page.tsx",
|
||||
"assets/js/src/newsletters/listings/heading_steps.tsx",
|
||||
"assets/js/src/newsletters/send/congratulate/success_pitch_mss.tsx",
|
||||
"assets/js/src/newsletters/types.tsx",
|
||||
"assets/js/src/segments/dynamic/dynamic_segments_filters/email_opens_absolute_count.tsx",
|
||||
"assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics.tsx",
|
||||
"assets/js/src/segments/dynamic/dynamic_segments_filters/subscriber_subscribed_date.tsx",
|
||||
"assets/js/src/segments/dynamic/dynamic_segments_filters/subscriber_wordpress_role.tsx",
|
||||
"assets/js/src/segments/dynamic/dynamic_segments_filters/woocommerce.tsx",
|
||||
"assets/js/src/segments/dynamic/dynamic_segments_filters/woocommerce_subscription.tsx",
|
||||
"assets/js/src/segments/dynamic/form.tsx",
|
||||
"assets/js/src/segments/dynamic/subscribers_calculator.ts",
|
||||
"assets/js/src/segments/dynamic/subscribers_counter.tsx",
|
||||
"assets/js/src/segments/dynamic/validator.ts",
|
||||
"assets/js/src/settings/components/segments_select.tsx",
|
||||
"assets/js/src/settings/pages/basics/stats_notifications.tsx",
|
||||
"assets/js/src/settings/pages/basics/subscribe_on.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/sending_frequency.tsx",
|
||||
"assets/js/src/settings/pages/send_with/send_with_choice.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/checkout_optin.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/email_customizer.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/enable_cookies.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/subscribe_old_customers.tsx",
|
||||
"assets/js/src/settings/store/actions/settings.ts",
|
||||
"assets/js/src/settings/store/controls.ts",
|
||||
"assets/js/src/settings/store/hooks/useActions.ts",
|
||||
"assets/js/src/settings/store/hooks/useSelector.ts",
|
||||
"assets/js/src/settings/store/hooks/useSetting.ts",
|
||||
"assets/js/src/settings/store/index.ts",
|
||||
"assets/js/src/settings/store/normalize_settings.ts",
|
||||
"assets/js/src/settings/store/selectors.ts",
|
||||
"assets/js/src/settings/store/types.ts",
|
||||
"assets/js/src/subscribers/importExport/export.ts"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/restrict-template-expressions": 0,
|
||||
"@typescript-eslint/no-unsafe-return": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
// there are so many violations of this rule we need to keep slowly removing it
|
||||
"files": [
|
||||
"assets/js/src/_storybook/action.ts",
|
||||
"assets/js/src/announcements/feature_announcement.tsx",
|
||||
"assets/js/src/announcements/with_feature_announcement.tsx",
|
||||
"assets/js/src/common/background/_stories/background.tsx",
|
||||
"assets/js/src/common/background/background.tsx",
|
||||
"assets/js/src/common/badge/_stories/badge.tsx",
|
||||
"assets/js/src/common/badge/badge.tsx",
|
||||
"assets/js/src/common/button/_stories/button.tsx",
|
||||
"assets/js/src/common/button/_stories/button_icons.tsx",
|
||||
"assets/js/src/common/button/button.tsx",
|
||||
"assets/js/src/common/categories/_stories/categories.tsx",
|
||||
"assets/js/src/common/categories/categories.tsx",
|
||||
"assets/js/src/common/categories/categories_item.tsx",
|
||||
"assets/js/src/common/controls/call_api.ts",
|
||||
"assets/js/src/common/controls/track_event.ts",
|
||||
"assets/js/src/common/datepicker/_stories/datepicker.tsx",
|
||||
"assets/js/src/common/datepicker/datepicker.tsx",
|
||||
"assets/js/src/common/form/checkbox/_stories/checkbox.tsx",
|
||||
"assets/js/src/common/form/checkbox/checkbox.tsx",
|
||||
"assets/js/src/common/form/checkbox/group.tsx",
|
||||
"assets/js/src/common/form/input/_stories/input.tsx",
|
||||
"assets/js/src/common/form/input/input.tsx",
|
||||
"assets/js/src/common/form/radio/_stories/radio.tsx",
|
||||
"assets/js/src/common/form/radio/group.tsx",
|
||||
"assets/js/src/common/form/radio/radio.tsx",
|
||||
"assets/js/src/common/form/react_select/_stories/react_select.tsx",
|
||||
"assets/js/src/common/form/react_select/react_select.tsx",
|
||||
"assets/js/src/common/form/select/_stories/select.tsx",
|
||||
"assets/js/src/common/form/textarea/_stories/textarea.tsx",
|
||||
"assets/js/src/common/form/textarea/textarea.tsx",
|
||||
"assets/js/src/common/form/toggle/_stories/toggle.tsx",
|
||||
"assets/js/src/common/form/toggle/toggle.tsx",
|
||||
"assets/js/src/common/form/yesno/_stories/yesno.tsx",
|
||||
"assets/js/src/common/form/yesno/yesno.tsx",
|
||||
"assets/js/src/common/functions/change_handlers.ts",
|
||||
"assets/js/src/common/hide_screen_options/hide_screen_options.tsx",
|
||||
"assets/js/src/common/listings/_stories/newsletter_stats.tsx",
|
||||
"assets/js/src/common/listings/_stories/newsletter_status.tsx",
|
||||
"assets/js/src/common/listings/newsletter_stats.tsx",
|
||||
"assets/js/src/common/listings/newsletter_stats/badge.tsx",
|
||||
"assets/js/src/common/listings/newsletter_stats/stats.tsx",
|
||||
"assets/js/src/common/listings/newsletter_status.tsx",
|
||||
"assets/js/src/common/loader/_stories/loader.tsx",
|
||||
"assets/js/src/common/loader/loader.tsx",
|
||||
"assets/js/src/common/modal/_stories/modal.tsx",
|
||||
"assets/js/src/common/modal/frame.tsx",
|
||||
"assets/js/src/common/modal/header.tsx",
|
||||
"assets/js/src/common/modal/modal.tsx",
|
||||
"assets/js/src/common/modal/overlay.tsx",
|
||||
"assets/js/src/common/premium_required/_stories/premium_required.tsx",
|
||||
"assets/js/src/common/premium_required/premium_required.tsx",
|
||||
"assets/js/src/common/preview/desktop_icon.tsx",
|
||||
"assets/js/src/common/preview/mobile_icon.tsx",
|
||||
"assets/js/src/common/remove_wrap_margin/remove_wrap_margin.tsx",
|
||||
"assets/js/src/common/set_from_address_modal.tsx",
|
||||
"assets/js/src/common/steps/_stories/steps.tsx",
|
||||
"assets/js/src/common/steps/content_wrapper_fix.tsx",
|
||||
"assets/js/src/common/steps/steps.tsx",
|
||||
"assets/js/src/common/steps/steps_content.tsx",
|
||||
"assets/js/src/common/subscribers_in_plan.tsx",
|
||||
"assets/js/src/common/tabs/_stories/tabs.tsx",
|
||||
"assets/js/src/common/tabs/_stories/tabs_icons.tsx",
|
||||
"assets/js/src/common/tabs/routed_tabs.tsx",
|
||||
"assets/js/src/common/tabs/tab.tsx",
|
||||
"assets/js/src/common/tabs/tabs.tsx",
|
||||
"assets/js/src/common/tag/_stories/tag.tsx",
|
||||
"assets/js/src/common/tag/_stories/tags.tsx",
|
||||
"assets/js/src/common/tag/tag.tsx",
|
||||
"assets/js/src/common/tag/tags.tsx",
|
||||
"assets/js/src/common/template_box/_stories/template_box.tsx",
|
||||
"assets/js/src/common/template_box/template_box.tsx",
|
||||
"assets/js/src/common/thumbnail.ts",
|
||||
"assets/js/src/common/tooltip/_stories/tooltip.tsx",
|
||||
"assets/js/src/common/tooltip/tooltip.tsx",
|
||||
"assets/js/src/common/top_bar/_stories/top_bar_no_children.tsx",
|
||||
"assets/js/src/common/top_bar/_stories/top_bar_with_children.tsx",
|
||||
"assets/js/src/common/top_bar/beamer_icon.tsx",
|
||||
"assets/js/src/common/top_bar/mailpoet_logo.tsx",
|
||||
"assets/js/src/common/top_bar/mailpoet_logo_mobile.tsx",
|
||||
"assets/js/src/common/top_bar/screen_options_fix.tsx",
|
||||
"assets/js/src/common/top_bar/top_bar.tsx",
|
||||
"assets/js/src/common/typography/heading/_stories/heading.tsx",
|
||||
"assets/js/src/common/typography/heading/heading.tsx",
|
||||
"assets/js/src/common/typography/list/_stories/list.tsx",
|
||||
"assets/js/src/common/typography/list/list.tsx",
|
||||
"assets/js/src/form_editor/store/actions.ts",
|
||||
"assets/js/src/form_editor/store/mapping/from_blocks/styles_mapper.ts",
|
||||
"assets/js/src/form_editor/store/mapping/to_blocks/styles_mapper.ts",
|
||||
"assets/js/src/form_editor/store/reducers/change_active_sidebar.ts",
|
||||
"assets/js/src/form_editor/store/reducers/history_record.ts",
|
||||
"assets/js/src/form_editor/store/reducers/toggle_form.ts",
|
||||
"assets/js/src/form_editor/store/reducers/toggle_fullscreen.ts",
|
||||
"assets/js/src/form_editor/store/reducers/toggle_sidebar.ts",
|
||||
"assets/js/src/form_editor/store/reducers/tutorial_dismiss.ts",
|
||||
"assets/js/src/form_editor/template_selection.tsx",
|
||||
"assets/js/src/form_editor/translations.ts",
|
||||
"assets/js/src/form_editor/utils/link_suggestions.tsx",
|
||||
"assets/js/src/newsletters/automatic_emails/events/event_options.tsx",
|
||||
"assets/js/src/newsletters/campaign_stats/newsletter_general_stats.tsx",
|
||||
"assets/js/src/newsletters/campaign_stats/newsletter_stats_info.tsx",
|
||||
"assets/js/src/newsletters/campaign_stats/page.tsx",
|
||||
"assets/js/src/notices/api_errors_notice.tsx",
|
||||
"assets/js/src/notices/invalid_mss_key_notice.tsx",
|
||||
"assets/js/src/notices/notice.tsx",
|
||||
"assets/js/src/notices/transactional_emails_propose_opt_in_notice.tsx",
|
||||
"assets/js/src/sending-paused-notices-fix-button.tsx",
|
||||
"assets/js/src/settings/components/inputs.tsx",
|
||||
"assets/js/src/settings/components/label.tsx",
|
||||
"assets/js/src/settings/components/pages_select.tsx",
|
||||
"assets/js/src/settings/components/save_button.tsx",
|
||||
"assets/js/src/settings/components/segments_select.tsx",
|
||||
"assets/js/src/settings/index.tsx",
|
||||
"assets/js/src/settings/pages/advanced/advanced.tsx",
|
||||
"assets/js/src/settings/pages/advanced/bounce_address.tsx",
|
||||
"assets/js/src/settings/pages/advanced/captcha.tsx",
|
||||
"assets/js/src/settings/pages/advanced/inactive_subscribers.tsx",
|
||||
"assets/js/src/settings/pages/advanced/libs_3rd_party.tsx",
|
||||
"assets/js/src/settings/pages/advanced/logging.tsx",
|
||||
"assets/js/src/settings/pages/advanced/reinstall.tsx",
|
||||
"assets/js/src/settings/pages/advanced/roles.tsx",
|
||||
"assets/js/src/settings/pages/advanced/share_data.tsx",
|
||||
"assets/js/src/settings/pages/advanced/task_scheduler.tsx",
|
||||
"assets/js/src/settings/pages/advanced/tracking.tsx",
|
||||
"assets/js/src/settings/pages/advanced/transactional.tsx",
|
||||
"assets/js/src/settings/pages/basics/basics.tsx",
|
||||
"assets/js/src/settings/pages/basics/default_sender.tsx",
|
||||
"assets/js/src/settings/pages/basics/gdpr_compliant.tsx",
|
||||
"assets/js/src/settings/pages/basics/manage_subscription.tsx",
|
||||
"assets/js/src/settings/pages/basics/new_subscriber_notifications.tsx",
|
||||
"assets/js/src/settings/pages/basics/shortcode.tsx",
|
||||
"assets/js/src/settings/pages/basics/stats_notifications.tsx",
|
||||
"assets/js/src/settings/pages/basics/subscribe_on.tsx",
|
||||
"assets/js/src/settings/pages/basics/unsubscribe_page.tsx",
|
||||
"assets/js/src/settings/pages/key_activation/key_activation.tsx",
|
||||
"assets/js/src/settings/pages/key_activation/messages/key_messages.tsx",
|
||||
"assets/js/src/settings/pages/key_activation/messages/mss_messages.tsx",
|
||||
"assets/js/src/settings/pages/key_activation/messages/premium_messages.tsx",
|
||||
"assets/js/src/settings/pages/key_activation/messages/service_unavailable_messages.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/activate_or_cancel.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/amazon_ses_fields.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/other_sending_methods.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/php_mail_fields.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/sendgrid_fields.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/sending_frequency.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/sending_method.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/smtp_fields.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/spf.tsx",
|
||||
"assets/js/src/settings/pages/send_with/other/test_sending.tsx",
|
||||
"assets/js/src/settings/pages/send_with/send_with.tsx",
|
||||
"assets/js/src/settings/pages/send_with/send_with_choice.tsx",
|
||||
"assets/js/src/settings/pages/signup_confirmation/confirmation_page.tsx",
|
||||
"assets/js/src/settings/pages/signup_confirmation/email_content.tsx",
|
||||
"assets/js/src/settings/pages/signup_confirmation/email_subject.tsx",
|
||||
"assets/js/src/settings/pages/signup_confirmation/enable_signup_confirmation.tsx",
|
||||
"assets/js/src/settings/pages/signup_confirmation/signup_confirmation.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/checkout_optin.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/email_customizer.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/enable_cookies.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/subscribe_old_customers.tsx",
|
||||
"assets/js/src/settings/pages/woo_commerce/woo_commerce.tsx",
|
||||
"assets/js/src/settings/settings.tsx",
|
||||
"assets/js/src/settings/store/actions/mss_and_premium.ts",
|
||||
"assets/js/src/settings/store/actions/open_woocommerce_customizer.ts",
|
||||
"assets/js/src/settings/store/actions/reinstall.ts",
|
||||
"assets/js/src/settings/store/actions/send_test_email.ts",
|
||||
"assets/js/src/settings/store/actions/settings.ts",
|
||||
"assets/js/src/settings/store/controls.ts",
|
||||
"assets/js/src/settings/store/create_reducer.ts",
|
||||
"assets/js/src/settings/store/index.ts",
|
||||
"assets/js/src/settings/store/make_default_state.ts",
|
||||
"assets/js/src/settings/store/selectors.ts"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
6971
eslint-config/package-lock.json
generated
Normal file
6971
eslint-config/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
eslint-config/package.json
Normal file
21
eslint-config/package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@mailpoet/eslint-config",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.11.0",
|
||||
"@typescript-eslint/parser": "^5.11.0",
|
||||
"eslint": "^8.8.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-import-resolver-webpack": "^0.13.2",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-no-only-tests": "^2.6.0",
|
||||
"eslint-plugin-react": "^7.28.0",
|
||||
"eslint-plugin-react-hooks": "^4.3.0"
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
{
|
||||
"presets": [
|
||||
["@babel/preset-react", { "runtime": "automatic" }],
|
||||
"@babel/preset-env",
|
||||
["@babel/preset-typescript", { "allowDeclareFields": true }]
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-env"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||
"babel-plugin-typescript-to-proptypes",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
[
|
||||
"@babel/plugin-transform-runtime",
|
||||
{
|
||||
@ -12,7 +15,18 @@
|
||||
"corejs": 3
|
||||
}
|
||||
],
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-syntax-import-meta",
|
||||
"@babel/plugin-proposal-json-strings",
|
||||
[
|
||||
"@babel/plugin-proposal-decorators",
|
||||
{
|
||||
"legacy": true
|
||||
}
|
||||
],
|
||||
"@babel/plugin-proposal-function-sent",
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-throw-expressions"
|
||||
]
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ WP_TEST_MAILER_ENABLE_SENDING=true
|
||||
WP_TEST_ENABLE_NETWORK_TESTS=true
|
||||
|
||||
# Optional: for multisite acceptance tests
|
||||
WP_ROOT_MULTISITE=/var/www/html
|
||||
WP_ROOT_MULTISITE=/var/www/wordpress
|
||||
WP_TEST_MULTISITE_SLUG=
|
||||
HTTP_HOST= # URL of your site (used for multisite env, equals to DOMAIN_CURRENT_SITE from wp-config.php)
|
||||
|
||||
@ -37,20 +37,3 @@ WP_GITHUB_TOKEN=
|
||||
# Jira username/email and a token from https://id.atlassian.com/manage/api-tokens:
|
||||
WP_JIRA_USER=
|
||||
WP_JIRA_TOKEN=
|
||||
|
||||
# k6 performance test suite
|
||||
# Get following secrets from the Secret Store, look for "MailPoet: plugin .env":
|
||||
WP_TEST_PERFORMANCE_DATA_URL=
|
||||
WP_TEST_PERFORMANCE_PW=
|
||||
K6_CLOUD_TOKEN=
|
||||
K6_CLOUD_ID=
|
||||
|
||||
# git hooks configuration (must be 'true' to enable)
|
||||
MP_GIT_HOOKS_ENABLE=true
|
||||
MP_GIT_HOOKS_ESLINT=true
|
||||
MP_GIT_HOOKS_STYLELINT=true
|
||||
MP_GIT_HOOKS_PHPLINT=true
|
||||
MP_GIT_HOOKS_CODE_SNIFFER=true
|
||||
MP_GIT_HOOKS_PHPSTAN=true
|
||||
MP_GIT_HOOKS_INSTALL_JS=false
|
||||
MP_GIT_HOOKS_INSTALL_PHP=false
|
||||
|
3
mailpoet/.eslintignore
Normal file
3
mailpoet/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
**/vendor/**
|
||||
**/vendor-prefixed/**
|
||||
**/testBundles/**
|
6
mailpoet/.gitignore
vendored
6
mailpoet/.gitignore
vendored
@ -8,10 +8,11 @@ tests/_output/*
|
||||
tests/_support/_generated/*
|
||||
tests/plugins
|
||||
.env
|
||||
.transifexrc
|
||||
/views/cache/**
|
||||
temp
|
||||
mailpoet.zip
|
||||
tests/javascript-newsletter-editor/testBundles
|
||||
tests/javascript_newsletter_editor/testBundles
|
||||
assets/dist
|
||||
.vagrant
|
||||
lang
|
||||
@ -26,4 +27,5 @@ tasks/code_sniffer/vendor
|
||||
tasks/phpstan/vendor
|
||||
tasks/phpstan/_phpstan-wp-source.neon
|
||||
/tools/vendor
|
||||
assets/js/src/newsletter-editor/behaviors/tinymce-icons.js
|
||||
/storybook-static
|
||||
assets/js/src/newsletter_editor/behaviors/tinymce_icons.js
|
||||
|
@ -1,2 +1 @@
|
||||
# we can set this back to "true" once @woocommerce/components have less restrictive definitions
|
||||
engine-strict=false
|
||||
engine-strict=true
|
||||
|
1
mailpoet/.nvmrc
Normal file
1
mailpoet/.nvmrc
Normal file
@ -0,0 +1 @@
|
||||
v16.13.0
|
48
mailpoet/.storybook/main.js
Normal file
48
mailpoet/.storybook/main.js
Normal file
@ -0,0 +1,48 @@
|
||||
const path = require('path');
|
||||
|
||||
const modulesDir = path.join( __dirname, '../node_modules' );
|
||||
console.log('NODE', modulesDir);
|
||||
// Workaround for Emotion 11
|
||||
// https://github.com/storybookjs/storybook/pull/13300#issuecomment-783268111
|
||||
const updateEmotionAliases = (config) => ({
|
||||
...config,
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
...config.resolve.alias,
|
||||
'@emotion/core': path.join(modulesDir, '@emotion/react'),
|
||||
'@emotion/styled': path.join(modulesDir, '@emotion/styled'),
|
||||
'@emotion/styled-base': path.join(modulesDir, '@emotion/styled'),
|
||||
'emotion-theming': path.join(modulesDir, '@emotion/react'),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
core: {
|
||||
builder: 'webpack5',
|
||||
},
|
||||
stories: ['../assets/js/src/**/_stories/*.tsx'],
|
||||
webpackFinal: (config) => {
|
||||
config.resolve.modules = ['node_modules', '../assets/js/src'];
|
||||
return updateEmotionAliases(config);
|
||||
},
|
||||
managerWebpack: updateEmotionAliases,
|
||||
addons: [
|
||||
'@storybook/addon-actions',
|
||||
'@storybook/addon-links',
|
||||
'storybook-addon-performance/register',
|
||||
{
|
||||
name: '@storybook/addon-storysource',
|
||||
options: {
|
||||
rule: {
|
||||
test: [/_stories\/.*\.tsx?$/],
|
||||
include: [path.resolve(__dirname, '../assets/js/src')],
|
||||
},
|
||||
loaderOptions: {
|
||||
parser: 'typescript',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
9
mailpoet/.storybook/preview.js
Normal file
9
mailpoet/.storybook/preview.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { addDecorator } from '@storybook/react';
|
||||
import { withPerformance } from 'storybook-addon-performance';
|
||||
import '../assets/css/src/storybook/wordpress-5.8.2.css';
|
||||
import '../assets/dist/css/mailpoet-plugin.css';
|
||||
import '../assets/dist/css/mailpoet-form-editor.css';
|
||||
|
||||
addDecorator(withPerformance);
|
||||
addDecorator(story => <div className="wp-core-ui" id="wpbody"><div id="mailpoet-modal"></div>{story()}</div>);
|
@ -1,41 +1,110 @@
|
||||
{
|
||||
'plugins': ['stylelint-order', 'stylelint-scss'],
|
||||
'customSyntax': 'postcss-scss',
|
||||
'rules':
|
||||
{
|
||||
'block-no-empty': true,
|
||||
'color-hex-length': 'short',
|
||||
'color-no-invalid-hex': true,
|
||||
'comment-no-empty': true,
|
||||
'comment-whitespace-inside': 'always',
|
||||
'declaration-block-no-duplicate-properties':
|
||||
[true, { ignore: ['consecutive-duplicates-with-different-values'] }],
|
||||
'declaration-block-no-redundant-longhand-properties':
|
||||
[true, { ignoreShorthands: [/flex/, /grid/] }],
|
||||
'declaration-block-single-line-max-declarations': 1,
|
||||
'declaration-empty-line-before': 'never',
|
||||
'font-family-no-duplicate-names': true,
|
||||
'function-name-case': 'lower',
|
||||
'function-url-quotes': 'always',
|
||||
'keyframe-declaration-no-important': true,
|
||||
'length-zero-no-unit': true,
|
||||
'media-feature-name-no-unknown': true,
|
||||
'no-duplicate-selectors': true,
|
||||
'order/properties-alphabetical-order': true,
|
||||
'property-no-unknown': true,
|
||||
'scss/at-rule-no-unknown': true,
|
||||
'scss/dollar-variable-colon-space-after': 'always',
|
||||
'scss/dollar-variable-colon-space-before': 'never',
|
||||
'scss/operator-no-newline-before': true,
|
||||
'scss/operator-no-unspaced': true,
|
||||
'scss/selector-no-redundant-nesting-selector': true,
|
||||
'selector-nested-pattern': '^(?!&-|&_).*',
|
||||
'selector-pseudo-class-no-unknown': true,
|
||||
'selector-pseudo-element-colon-notation': 'single',
|
||||
'selector-pseudo-element-no-unknown': true,
|
||||
'selector-type-case': 'lower',
|
||||
'shorthand-property-no-redundant-values': true,
|
||||
'string-no-newline': true,
|
||||
'unit-no-unknown': true,
|
||||
},
|
||||
"plugins": [
|
||||
"stylelint-order",
|
||||
"stylelint-scss"
|
||||
],
|
||||
"customSyntax": "postcss-scss",
|
||||
"rules": {
|
||||
"at-rule-empty-line-before": ["always", {
|
||||
except: ["first-nested", "blockless-after-blockless"],
|
||||
}],
|
||||
"at-rule-name-case": "lower",
|
||||
"at-rule-semicolon-newline-after": "always",
|
||||
"block-closing-brace-empty-line-before": "never",
|
||||
"block-closing-brace-newline-after": "always",
|
||||
"block-closing-brace-newline-before": "always-multi-line",
|
||||
"block-closing-brace-space-before": "always-single-line",
|
||||
"block-no-empty": true,
|
||||
"block-opening-brace-newline-after": "always-multi-line",
|
||||
"block-opening-brace-space-after": "always-single-line",
|
||||
"block-opening-brace-space-before": "always",
|
||||
"color-hex-case": "lower",
|
||||
"color-hex-length": "short",
|
||||
"color-no-invalid-hex": true,
|
||||
"comment-no-empty": true,
|
||||
"comment-whitespace-inside": "always",
|
||||
"declaration-bang-space-after": "never",
|
||||
"declaration-bang-space-before": "always",
|
||||
"declaration-block-no-duplicate-properties": [true, {
|
||||
ignore: ["consecutive-duplicates-with-different-values"],
|
||||
}],
|
||||
"declaration-block-no-redundant-longhand-properties": [true, {
|
||||
ignoreShorthands: [/flex/, /grid/]
|
||||
}],
|
||||
"declaration-block-semicolon-newline-after": "always-multi-line",
|
||||
"declaration-block-semicolon-space-after": "always-single-line",
|
||||
"declaration-block-semicolon-space-before": "never",
|
||||
"declaration-block-single-line-max-declarations": 1,
|
||||
"declaration-colon-newline-after": "always-multi-line",
|
||||
"declaration-colon-space-after": "always-single-line",
|
||||
"declaration-colon-space-before": "never",
|
||||
"declaration-empty-line-before": "never",
|
||||
"font-family-no-duplicate-names": true,
|
||||
"function-comma-space-after": "always-single-line",
|
||||
"function-comma-space-before": "never",
|
||||
"function-max-empty-lines": 0,
|
||||
"function-name-case": "lower",
|
||||
"function-parentheses-newline-inside": "always-multi-line",
|
||||
"function-parentheses-space-inside": "never-single-line",
|
||||
"function-url-quotes": "always",
|
||||
"function-whitespace-after": "always",
|
||||
"indentation": 2,
|
||||
"keyframe-declaration-no-important": true,
|
||||
"length-zero-no-unit": true,
|
||||
"max-empty-lines": 1,
|
||||
"media-feature-colon-space-after": "always",
|
||||
"media-feature-colon-space-before": "never",
|
||||
"media-feature-name-case": "lower",
|
||||
"media-feature-name-no-unknown": true,
|
||||
"media-feature-parentheses-space-inside": "never",
|
||||
"media-feature-range-operator-space-after": "always",
|
||||
"media-query-list-comma-newline-after": "always-multi-line",
|
||||
"media-query-list-comma-space-after": "always-single-line",
|
||||
"media-query-list-comma-space-before": "never",
|
||||
"no-duplicate-selectors": true,
|
||||
"no-eol-whitespace": true,
|
||||
"no-extra-semicolons": true,
|
||||
"no-missing-end-of-source-newline": true,
|
||||
"number-leading-zero": "never",
|
||||
"number-no-trailing-zeros": true,
|
||||
"order/properties-alphabetical-order": true,
|
||||
"property-case": "lower",
|
||||
"property-no-unknown": true,
|
||||
"rule-empty-line-before": ["always-multi-line", {
|
||||
except: ["first-nested"],
|
||||
ignore: ["after-comment"]
|
||||
}],
|
||||
"scss/at-rule-no-unknown": true,
|
||||
"scss/dollar-variable-colon-space-after": "always",
|
||||
"scss/dollar-variable-colon-space-before": "never",
|
||||
"scss/operator-no-newline-after": true,
|
||||
"scss/operator-no-newline-before": true,
|
||||
"scss/operator-no-unspaced": true,
|
||||
"scss/selector-no-redundant-nesting-selector": true,
|
||||
"selector-attribute-brackets-space-inside": "never",
|
||||
"selector-attribute-operator-space-after": "never",
|
||||
"selector-attribute-operator-space-before": "never",
|
||||
"selector-combinator-space-after": "always",
|
||||
"selector-combinator-space-before": "always",
|
||||
"selector-list-comma-newline-after": "always",
|
||||
"selector-list-comma-space-before": "never",
|
||||
"selector-max-empty-lines": 0,
|
||||
"selector-nested-pattern": "^(?!&-|&_).*",
|
||||
"selector-pseudo-class-case": "lower",
|
||||
"selector-pseudo-class-no-unknown": true,
|
||||
"selector-pseudo-class-parentheses-space-inside": "never",
|
||||
"selector-pseudo-element-case": "lower",
|
||||
"selector-pseudo-element-colon-notation": "single",
|
||||
"selector-pseudo-element-no-unknown": true,
|
||||
"selector-type-case": "lower",
|
||||
"shorthand-property-no-redundant-values": true,
|
||||
"string-no-newline": true,
|
||||
"string-quotes": "single",
|
||||
"unit-case": "lower",
|
||||
"unit-no-unknown": true,
|
||||
"value-list-comma-newline-after": "always-multi-line",
|
||||
"value-list-comma-space-after": "always-single-line",
|
||||
"value-list-comma-space-before": "never",
|
||||
"value-list-max-empty-lines": 0,
|
||||
},
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[o:wysija:p:mp3:r:mailpoet]
|
||||
file_filter = lang/mailpoet-<lang>.po
|
||||
source_file = lang/mailpoet.pot
|
||||
source_lang = en_US
|
||||
type = PO
|
||||
[mp3.mailpoet]
|
||||
file_filter = lang/mailpoet-<lang>.po
|
||||
minimum_perc = 30
|
||||
source_file = lang/mailpoet.pot
|
||||
source_lang = en_US
|
||||
type = PO
|
||||
|
@ -1,33 +1,26 @@
|
||||
### Table of Contents
|
||||
# MailPoet
|
||||
The **MailPoet** plugin.
|
||||
|
||||
1. [MailPoet](#mailpoet)
|
||||
2. [Setup](#setup)
|
||||
1. [Requirements](#requirements)
|
||||
2. [Installation](#installation)
|
||||
3. [Frameworks and libraries](#frameworks-and-libraries)
|
||||
3. [Workflow Commands](#workflow-commands)
|
||||
4. [Coding and Testing](#coding-and-testing)
|
||||
1. [DI](#di)
|
||||
2. [PHP-Scoper](#php-scoper)
|
||||
3. [i18n](#i18n)
|
||||
4. [Acceptance testing](#acceptance-testing)
|
||||
To use the official Docker-based development environment, see details
|
||||
in [the readme file](../README.md) in the root of this repository. If
|
||||
you'd like to use the plugin code directly, you can follow the instructions
|
||||
below.
|
||||
|
||||
## MailPoet
|
||||
## Contents
|
||||
|
||||
- For help with product, visit [SUPPORT](../SUPPORT.md).
|
||||
- To use the Docker-based development environment, see [monorepo README](../README.md).
|
||||
- To use plugin code directly, follow instructions below.
|
||||
- [Setup](#setup)
|
||||
- [Frameworks and libraries](#frameworks-and-libraries)
|
||||
- [Workflow Commands](#workflow-commands)
|
||||
- [Coding and Testing](#coding-and-testing)
|
||||
|
||||
## Setup
|
||||
|
||||
### Requirements
|
||||
|
||||
- PHP >= 7.4
|
||||
- PHP >= 7.3 (only for the development environment, to run the plugin PHP >= 7.2 is required)
|
||||
- NodeJS
|
||||
- WordPress
|
||||
|
||||
### Installation
|
||||
|
||||
The instructions below assume you already have a working WordPress development environment:
|
||||
|
||||
```bash
|
||||
@ -50,8 +43,9 @@ cp .env.sample .env
|
||||
./do compile:all
|
||||
```
|
||||
|
||||
### Frameworks and libraries
|
||||
## Frameworks and libraries
|
||||
|
||||
- [Paris ORM](https://github.com/j4mie/paris).
|
||||
- [Symfony/dependency-injection](https://github.com/symfony/dependency-injection) ([docs for 3.4](https://symfony.com/doc/3.4/components/dependency_injection.html)).
|
||||
- [PHP-Scoper](https://github.com/humbug/php-scoper) for moving dependencies into MP namespace
|
||||
- [Twig](https://twig.symfony.com/) and [Handlebars](https://handlebarsjs.com/) are used for templates rendering.
|
||||
@ -68,13 +62,6 @@ cp .env.sample .env
|
||||
|
||||
## Workflow Commands
|
||||
|
||||
There are two different `./do` commands. One is in the free MailPoet directory and runs the commands on the local computer. The second is in the repository root and runs the commands in a Docker container.
|
||||
Running `./do` commands in the repository root will run the command in the Docker container.
|
||||
|
||||
It is recommended to run the assets commands directly in the free MailPoet directory. That means installing the dependencies locally. Running the js and css compilation commands within the container is possible, but it is slower.
|
||||
|
||||
On the other hand, the tests should be run in the container. The container has all the necessary dependencies installed and configured. And there is a database running. See more details in the README.md in the repository root.
|
||||
|
||||
```bash
|
||||
$ ./do install # install PHP and JS dependencies
|
||||
$ ./do update # update PHP and JS dependencies
|
||||
@ -100,6 +87,7 @@ $ ./do test:debug-unit # alias for ./do test:unit --debug
|
||||
$ ./do test:debug-integration # alias for ./do test:integration --debug
|
||||
$ ./do test:failed-unit # run the last failing unit test.
|
||||
$ ./do test:failed-integration # run the last failing integration test.
|
||||
$ ./do test:coverage # run tests and output coverage information.
|
||||
$ ./do test:javascript # run the JS tests.
|
||||
$ ./do test:acceptance [--file=...] [--skip-deps]
|
||||
# run acceptances tests into a docker environment.
|
||||
@ -127,6 +115,34 @@ $ ./do container:dump # Generates DI container cache.
|
||||
$ ./do generate:data [<generatorName>] [<threads>] # Generates random usage data (Note: requires WooCommerce active) e.g. ./do generate:data past_revenues 4
|
||||
```
|
||||
|
||||
## Storybook
|
||||
|
||||
We use [Storybook.js](https://storybook.js.org/) to showcase our React components, which can be used throughout the plugin.
|
||||
|
||||
### Usage
|
||||
|
||||
Currently, we don't have Storybook published publicly, so developers need to run or build it locally.
|
||||
|
||||
To run it locally (on `http://localhost:8083`) while watching the changes (recommended when developing new component), run
|
||||
|
||||
```bash
|
||||
./do storybook:watch
|
||||
```
|
||||
|
||||
To build the static version, which can be accessed via browser, run
|
||||
|
||||
```bash
|
||||
./do storybook:build
|
||||
```
|
||||
|
||||
which will create a `storybook-static` folder with all necessary files. Don't forget to rebuild it when new components are added.
|
||||
|
||||
### Building new components
|
||||
|
||||
- All stories should be located in `_stories` folder inside the component folder they belong to.
|
||||
- Run `./do storybook:watch` so all changes are automatically reflected in `http://localhost:8083`.
|
||||
- Examples are available in `assets/js/src/storybook_demo/_stories` folder.
|
||||
|
||||
## Coding and Testing
|
||||
|
||||
### DI
|
||||
@ -142,86 +158,52 @@ Dependencies handled by PHP-Scoper are configured in extra configuration files `
|
||||
|
||||
### i18n
|
||||
|
||||
We use functions `__()`, `_n()`, `_x()`, and `_nx()` with domain `mailpoet` to translate strings. Please follow [best practices](https://codex.wordpress.org/I18n_for_WordPress_Developers).
|
||||
We use functions `__()`, `_n()` and `_x()` with domain `mailpoet` to translate strings.
|
||||
|
||||
#### Comments for translators
|
||||
|
||||
When the translation string can be ambiguous, add [a translators comment](https://codex.wordpress.org/I18n_for_WordPress_Developers#Descriptions) for clarification. Don't use `_x()` or `_xn()` for clarification.
|
||||
|
||||
```php
|
||||
// translators:
|
||||
$customErrorMessage = sprintf(
|
||||
// translators: %1$s is the link, %2$s is the error message.
|
||||
__('Please see %1$s for more information. %2$s.', 'mailpoet'),
|
||||
'https://kb.mailpoet.com',
|
||||
$errorMessage
|
||||
);
|
||||
```
|
||||
|
||||
#### In PHP code
|
||||
**in PHP code**
|
||||
|
||||
```php
|
||||
__('text to translate', 'mailpoet');
|
||||
_n('single text', 'plural text', $number, 'mailpoet');
|
||||
_x('text to translate', 'context', 'mailpoet');
|
||||
_xn('single text', 'plural text', $number, 'context', 'mailpoet');
|
||||
_x('text to translate', 'context for translators', 'mailpoet');
|
||||
```
|
||||
|
||||
#### In JavaScript/TypeScript code
|
||||
**in Twig views**
|
||||
|
||||
```ts
|
||||
import { __, _n, _x, _xn } from '@wordpress/i18n';
|
||||
|
||||
__('text to translate', 'mailpoet');
|
||||
_n('single text', 'plural text', number, 'mailpoet');
|
||||
_x('text to translate', 'context', 'mailpoet');
|
||||
_nx('single text', 'plural text', number, 'context', 'mailpoet');
|
||||
```html
|
||||
<%= __('text to translate') %>
|
||||
<%= _n('single text', 'plural text', $number) %>
|
||||
<%= _x('text to translate', 'context for translators') %>
|
||||
```
|
||||
|
||||
To replace placeholders in translated strings, use `sprintf`:
|
||||
The domain `mailpoet` will be added automatically by the Twig functions.
|
||||
|
||||
```ts
|
||||
import { sprintf } from '@wordpress/i18n';
|
||||
**in Javascript code**
|
||||
|
||||
sprintf(__('Hello %s', 'mailpoet'), 'John');
|
||||
First add the string to the translations block in the Twig view:
|
||||
|
||||
```html
|
||||
<% block translations %>
|
||||
<%= localize({
|
||||
'key': __('string to translate'),
|
||||
...
|
||||
}) %>
|
||||
<% endblock %>
|
||||
```
|
||||
|
||||
To replace React elements use `createInterpolateElement`:
|
||||
|
||||
```tsx
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { createInterpolateElement } from '@wordpress/element';
|
||||
import { CustomComponent } from '../custom-component.js';
|
||||
|
||||
const translatedString = createInterpolateElement(
|
||||
__(
|
||||
'This is a <span>string</span> with a <a>link</a> and a self-closing <custom_component/>.',
|
||||
),
|
||||
{
|
||||
span: <span class="special-text" />,
|
||||
a: <a href="https://make.wordpress.org" />,
|
||||
custom_component: <CustomComponent />,
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
For more information, see the [@wordpress/i18n](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/)
|
||||
and the [createInterpolateElement](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-element/#createinterpolateelement)
|
||||
guides.
|
||||
Then use `MailPoet.I18n.t('key')` to get the translated string on your Javascript code.
|
||||
|
||||
### Acceptance testing
|
||||
|
||||
To run the whole acceptance testing suite you need the docker daemon to be running and after that use a command: `./do test:acceptance`.
|
||||
If you want to run only a single test use the parameter `--file`:
|
||||
|
||||
```bash
|
||||
./do test:acceptance --skip-deps --file tests/acceptance/ReceiveStandardEmailCest.php
|
||||
```
|
||||
|
||||
The argument `--skip-deps` is useful locally to speed up the run.
|
||||
|
||||
If there are some unexpected errors you can delete all the runtime and start again.
|
||||
To delete all the docker runtime for acceptance tests use the command `./do delete:docker`.
|
||||
To delete all the docker runtime for acceptance tests use the command `./do d:d`.
|
||||
|
||||
When debugging you can add `$i->pause();` in to your test which pauses the execution.
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user