Merge branch 'trunk' into update/marketplace-1

This commit is contained in:
And Finally 2021-08-06 12:37:37 +01:00
commit b2ae8ab1b4
14 changed files with 275 additions and 82 deletions

View File

@ -4,29 +4,39 @@ on:
types: [closed] types: [closed]
jobs: jobs:
assign-milestone: process-pull-request-after-merge:
name: "Assign milestone to merged pull request" name: "Process a pull request after it's merged"
if: github.event.pull_request.merged == true && ! github.event.pull_request.milestone if: github.event.pull_request.merged == true
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Get the milestone changer script" - name: "Get the action scripts"
run: | run: |
curl \ scripts="assign-milestone-to-merged-pr.php add-post-merge-comment.php post-request-shared.php"
--silent \ for script in $scripts
--fail \ do
--header 'Authorization: bearer ${{ secrets.GITHUB_TOKEN }}' \ curl \
--header 'User-Agent: GitHub action to set the milestone for a pull request' \ --silent \
--header 'Accept: application/vnd.github.v3.raw' \ --fail \
--remote-name \ --header 'Authorization: bearer ${{ secrets.GITHUB_TOKEN }}' \
--location $GITHUB_API_URL/repos/${{ github.repository }}/contents/.github/workflows/scripts/assign-milestone-to-merged-pr.php --header 'User-Agent: GitHub action to set the milestone for a pull request' \
env: --header 'Accept: application/vnd.github.v3.raw' \
GITHUB_API_URL: ${{ env.GITHUB_API_URL }} --output $script \
- name: "Install PHP" --location "$GITHUB_API_URL/repos/${{ github.repository }}/contents/.github/workflows/scripts/$script?ref=${{ github.event.pull_request.base.ref }}"
uses: shivammathur/setup-php@v2 done
with: env:
php-version: '7.4' GITHUB_API_URL: ${{ env.GITHUB_API_URL }}
- name: "Run the milestone changer script" - name: "Install PHP"
run: php assign-milestone-to-merged-pr.php uses: shivammathur/setup-php@v2
env: with:
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }} php-version: '7.4'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: "Run the script to assign a milestone"
if: "!github.event.pull_request.milestone"
run: php assign-milestone-to-merged-pr.php
env:
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Run the script to post a comment with next steps hint"
run: php add-post-merge-comment.php
env:
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,95 @@
<?php
/**
* Script to automatically add a comment to a pull request when it's merged.
*
* @package WooCommerce/GithubActions
*/
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
require_once __DIR__ . '/post-request-shared.php';
/*
* Get the merger login name.
*/
echo 'Retrieving the merger user name... ';
$get_pr_merged_username_query = "
node(id: \"$pr_id\") {
... on PullRequest {
timelineItems(first: 1, itemTypes: MERGED_EVENT) {
edges {
node {
... on MergedEvent {
actor {
login
}
}
}
}
}
}
}";
$result = do_graphql_api_request( $get_pr_merged_username_query );
if ( is_array( $result ) ) {
if ( empty( $result['errors'] ) ) {
echo "Ok!\n";
} else {
echo "\n*** Errors found while retrieving the merger user name:\n";
echo var_dump( $result['errors'] );
return;
}
} else {
echo "\n*** Error found while retrieving the merger user name: file_get_contents returned the following:\n";
echo var_dump( $result );
return;
}
$merger_user_name = $result['data']['node']['timelineItems']['edges'][0]['node']['actor']['login'];
echo "The pull request was merged by: $merger_user_name\n";
/*
* Post the comment.
*/
$comment_body = "Hi @$merger_user_name, thanks for merging this pull request. Please take a look at these follow-up tasks you may need to perform:
- [ ] Add the `status: needs changelog` label
- [ ] Add the `status: needs testing instructions` label";
$add_comment_mutation = "
addComment(input: {subjectId: \"$pr_id\", body: \"$comment_body\", clientMutationId: \"$github_token\"}) {
commentEdge {
node {
id
databaseId
url
}
}
}";
echo 'Publishing the comment... ';
$result = do_graphql_api_request( $add_comment_mutation, true );
if ( is_array( $result ) ) {
if ( empty( $result['errors'] ) ) {
echo "Ok!\n";
} else {
echo "\n*** Errors found while publishing the comment:\n";
echo var_dump( $result['errors'] );
return;
}
} else {
echo "\n*** Error found while publishing the comment: file_get_contents returned the following:\n";
echo var_dump( $result );
return;
}
$comment_url = $result['data']['addComment']['commentEdge']['node']['url'];
echo "Comment URL: $comment_url\n";
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions

View File

@ -7,21 +7,9 @@
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
global $repo_owner, $repo_name, $github_token, $graphql_api_url; require_once __DIR__ . '/post-request-shared.php';
/** /*
* Grab/process input.
*/
$repo_parts = explode( '/', getenv( 'GITHUB_REPOSITORY' ) );
$repo_owner = $repo_parts[0];
$repo_name = $repo_parts[1];
$pr_id = getenv( 'PULL_REQUEST_ID' );
$github_token = getenv( 'GITHUB_TOKEN' );
$graphql_api_url = getenv( 'GITHUB_GRAPHQL_URL' );
/**
* Select the milestone to be added: * Select the milestone to be added:
* *
* 1. Get the first 10 milestones sorted by creation date descending. * 1. Get the first 10 milestones sorted by creation date descending.
@ -122,35 +110,4 @@ if ( is_array( $result ) ) {
echo var_dump( $result ); echo var_dump( $result );
} }
/**
* Function to query the GitHub GraphQL API.
*
* @param string $body The GraphQL-formatted request body, without "query" or "mutation" wrapper.
* @param bool $is_mutation True if the request is a mutation, false if it's a query.
* @return mixed The json-decoded response if a response is received, 'false' (or whatever file_get_contents returns) otherwise.
*/
function do_graphql_api_request( $body, $is_mutation = false ) {
global $github_token, $graphql_api_url;
$keyword = $is_mutation ? 'mutation' : 'query';
$data = array( 'query' => "$keyword { $body }" );
$context = stream_context_create(
array(
'http' => array(
'method' => 'POST',
'header' => array(
'Accept: application/json',
'Content-Type: application/json',
'User-Agent: GitHub action to set the milestone for a pull request',
'Authorization: bearer ' . $github_token,
),
'content' => json_encode( $data ),
),
)
);
$result = file_get_contents( $graphql_api_url, false, $context );
return is_string( $result ) ? json_decode( $result, true ) : $result;
}
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions

View File

@ -0,0 +1,56 @@
<?php
/**
* Common code for the post-merge GitHub action scripts.
*
* @package WooCommerce/GithubActions
*/
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions
global $repo_owner, $repo_name, $github_token, $graphql_api_url;
/*
* Grab/process input.
*/
$repo_parts = explode( '/', getenv( 'GITHUB_REPOSITORY' ) );
$repo_owner = $repo_parts[0];
$repo_name = $repo_parts[1];
$pr_id = getenv( 'PULL_REQUEST_ID' );
$github_token = getenv( 'GITHUB_TOKEN' );
$graphql_api_url = getenv( 'GITHUB_GRAPHQL_URL' );
/**
* Function to query the GitHub GraphQL API.
*
* @param string $body The GraphQL-formatted request body, without "query" or "mutation" wrapper.
* @param bool $is_mutation True if the request is a mutation, false if it's a query.
* @return mixed The json-decoded response if a response is received, 'false' (or whatever file_get_contents returns) otherwise.
*/
function do_graphql_api_request( $body, $is_mutation = false ) {
global $github_token, $graphql_api_url;
$keyword = $is_mutation ? 'mutation' : 'query';
$data = array( 'query' => "$keyword { $body }" );
$context = stream_context_create(
array(
'http' => array(
'method' => 'POST',
'header' => array(
'Accept: application/json',
'Content-Type: application/json',
'User-Agent: GitHub action to set the milestone for a pull request',
'Authorization: bearer ' . $github_token,
),
'content' => json_encode( $data ),
),
)
);
$result = file_get_contents( $graphql_api_url, false, $context );
return is_string( $result ) ? json_decode( $result, true ) : $result;
}
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions

View File

@ -21,6 +21,7 @@
* Fix - Replace hardcoded frontend JS script versions with WC version to bust cached/staled JS scripts. #30301 * Fix - Replace hardcoded frontend JS script versions with WC version to bust cached/staled JS scripts. #30301
* Fix - Variable product showing HTML content while granting access for downloadable product in orders. #30305 * Fix - Variable product showing HTML content while granting access for downloadable product in orders. #30305
* Fix - Replaced wp.passwordStrength deprecated method. #30191 * Fix - Replaced wp.passwordStrength deprecated method. #30191
* Fix - `woocommerce_email_settings` filter being triggered twice. #30404
* Dev - Apply `woocommerce_logout_default_redirect_url` filter to logout for custom endpoint. #29967 * Dev - Apply `woocommerce_logout_default_redirect_url` filter to logout for custom endpoint. #29967
* Dev - Added new `woocommerce_email_sent` hook. #30123 * Dev - Added new `woocommerce_email_sent` hook. #30123

View File

@ -1595,6 +1595,32 @@ return array(
'RSVO' => _x( 'Vojvodina', 'district', 'woocommerce' ), 'RSVO' => _x( 'Vojvodina', 'district', 'woocommerce' ),
), ),
'SE' => array(), 'SE' => array(),
'UA' => array( // Ukraine. Ref: https://en.wikipedia.org/wiki/Oblasts_of_Ukraine.
'VN' => __( 'Vinnytsia Oblast', 'woocommerce' ),
'VL' => __( 'Volyn Oblast', 'woocommerce' ),
'DP' => __( 'Dnipropetrovsk Oblast', 'woocommerce' ),
'DT' => __( 'Donetsk Oblast', 'woocommerce' ),
'ZT' => __( 'Zhytomyr Oblast', 'woocommerce' ),
'ZK' => __( 'Zakarpattia Oblast', 'woocommerce' ),
'ZP' => __( 'Zaporizhzhia Oblast', 'woocommerce' ),
'IF' => __( 'Ivano-Frankivsk Oblast', 'woocommerce' ),
'KV' => __( 'Kyiv Oblast', 'woocommerce' ),
'KH' => __( 'Kirovohrad Oblast', 'woocommerce' ),
'LH' => __( 'Luhansk Oblast', 'woocommerce' ),
'LV' => __( 'Lviv Oblast', 'woocommerce' ),
'MY' => __( 'Mykolaiv Oblast', 'woocommerce' ),
'OD' => __( 'Odessa Oblast', 'woocommerce' ),
'PL' => __( 'Poltava Oblast', 'woocommerce' ),
'RV' => __( 'Rivne Oblast', 'woocommerce' ),
'SM' => __( 'Sumy Oblast', 'woocommerce' ),
'TP' => __( 'Ternopil Oblast', 'woocommerce' ),
'KK' => __( 'Kharkiv Oblast', 'woocommerce' ),
'KS' => __( 'Kherson Oblast', 'woocommerce' ),
'KM' => __( 'Khmelnytskyi Oblast', 'woocommerce' ),
'CK' => __( 'Cherkasy Oblast', 'woocommerce' ),
'CH' => __( 'Chernihiv Oblast', 'woocommerce' ),
'CV' => __( 'Chernivtsi Oblast', 'woocommerce' ),
),
'UG' => array( // Uganda districts. Ref: https://en.wikipedia.org/wiki/ISO_3166-2:UG. 'UG' => array( // Uganda districts. Ref: https://en.wikipedia.org/wiki/ISO_3166-2:UG.
'UG314' => __( 'Abim', 'woocommerce' ), 'UG314' => __( 'Abim', 'woocommerce' ),
'UG301' => __( 'Adjumani', 'woocommerce' ), 'UG301' => __( 'Adjumani', 'woocommerce' ),

View File

@ -607,6 +607,10 @@ class WC_Meta_Box_Order_Data {
$payment_method_title = $methods[ $payment_method ]->get_title(); $payment_method_title = $methods[ $payment_method ]->get_title();
} }
if ( $payment_method == 'other') {
$payment_method_title = esc_html__( 'Other', 'woocommerce' );
}
$props['payment_method'] = $payment_method; $props['payment_method'] = $payment_method;
$props['payment_method_title'] = $payment_method_title; $props['payment_method_title'] = $payment_method_title;
} }

View File

@ -78,6 +78,14 @@ class WC_Customer extends WC_Legacy_Customer {
*/ */
protected $calculated_shipping = false; protected $calculated_shipping = false;
/**
* This is the name of this object type.
*
* @since 5.6.0
* @var string
*/
protected $object_type = 'customer';
/** /**
* Load customer data based on how WC_Customer is called. * Load customer data based on how WC_Customer is called.
* *
@ -118,16 +126,6 @@ class WC_Customer extends WC_Legacy_Customer {
} }
} }
/**
* Prefix for action and filter hooks on data.
*
* @since 3.0.0
* @return string
*/
protected function get_hook_prefix() {
return 'woocommerce_customer_get_';
}
/** /**
* Delete a customer and reassign posts.. * Delete a customer and reassign posts..
* *

View File

@ -1315,6 +1315,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
AND p.post_type = 'product' AND p.post_type = 'product'
", ",
'orderby' => '
ORDER BY RAND()',
'limits' => ' 'limits' => '
LIMIT ' . absint( $limit ) . ' LIMIT ' . absint( $limit ) . '
', ',

View File

@ -492,6 +492,19 @@ add_action( 'woocommerce_scheduled_sales', 'wc_scheduled_sales' );
* @return array * @return array
*/ */
function wc_get_attachment_image_attributes( $attr ) { function wc_get_attachment_image_attributes( $attr ) {
/*
* If the user can manage woocommerce, allow them to
* see the image content.
*/
if ( current_user_can( 'manage_woocommerce' ) ) {
return $attr;
}
/*
* If the user does not have the right capabilities,
* filter out the image source and replace with placeholder
* image.
*/
if ( isset( $attr['src'] ) && strstr( $attr['src'], 'woocommerce_uploads/' ) ) { if ( isset( $attr['src'] ) && strstr( $attr['src'], 'woocommerce_uploads/' ) ) {
$attr['src'] = wc_placeholder_img_src(); $attr['src'] = wc_placeholder_img_src();
@ -511,7 +524,19 @@ add_filter( 'wp_get_attachment_image_attributes', 'wc_get_attachment_image_attri
* @return array * @return array
*/ */
function wc_prepare_attachment_for_js( $response ) { function wc_prepare_attachment_for_js( $response ) {
/*
* If the user can manage woocommerce, allow them to
* see the image content.
*/
if ( current_user_can( 'manage_woocommerce' ) ) {
return $response;
}
/*
* If the user does not have the right capabilities,
* filter out the image source and replace with placeholder
* image.
*/
if ( isset( $response['url'] ) && strstr( $response['url'], 'woocommerce_uploads/' ) ) { if ( isset( $response['url'] ) && strstr( $response['url'], 'woocommerce_uploads/' ) ) {
$response['full']['url'] = wc_placeholder_img_src(); $response['full']['url'] = wc_placeholder_img_src();
if ( isset( $response['sizes'] ) ) { if ( isset( $response['sizes'] ) ) {

View File

@ -1,5 +1,3 @@
/* eslint-disable jest/no-export, jest/no-disabled-tests */
/** /**
* Internal dependencies * Internal dependencies
*/ */
@ -37,6 +35,10 @@ const runOnboardingFlowTest = () => {
await withRestApi.deleteAllShippingZones(); await withRestApi.deleteAllShippingZones();
}); });
it('can reset shipping classes', async () => {
await withRestApi.deleteAllShippingClasses();
})
it('can reset to default settings', async () => { it('can reset to default settings', async () => {
await withRestApi.resetSettingsGroupToDefault('general'); await withRestApi.resetSettingsGroupToDefault('general');
await withRestApi.resetSettingsGroupToDefault('products'); await withRestApi.resetSettingsGroupToDefault('products');
@ -55,7 +57,7 @@ const runTaskListTest = () => {
beforeAll(async () => { beforeAll(async () => {
await merchant.login(); await merchant.login();
}); });
it('can setup shipping', async () => { it('can setup shipping', async () => {
await page.evaluate(() => { await page.evaluate(() => {
document.querySelector('.woocommerce-list__item-title').scrollIntoView(); document.querySelector('.woocommerce-list__item-title').scrollIntoView();

View File

@ -12,6 +12,7 @@
- Added `describeIf()` to conditionally run a test suite - Added `describeIf()` to conditionally run a test suite
- Added `itIf()` to conditionally run a test case. - Added `itIf()` to conditionally run a test case.
- Added merchant workflows around plugins: `uploadAndActivatePlugin()`, `activatePlugin()`, `deactivatePlugin()`, `deletePlugin()` - Added merchant workflows around plugins: `uploadAndActivatePlugin()`, `activatePlugin()`, `deactivatePlugin()`, `deletePlugin()`
- Added `deleteAllShippingClasses()` which permanently deletes all shipping classes using the API
# 0.1.5 # 0.1.5

View File

@ -143,6 +143,7 @@ This package provides support for enabling retries in tests:
| `deleteAllCoupons` | | Permanently delete all coupons | | `deleteAllCoupons` | | Permanently delete all coupons |
| `deleteAllProducts` | | Permanently delete all products | | `deleteAllProducts` | | Permanently delete all products |
| `deleteAllShippingZones` | | Permanently delete all shipping zones except the default | | `deleteAllShippingZones` | | Permanently delete all shipping zones except the default |
| `deleteAllShippingClasses` | Permanently delete all shipping classes |
| `deleteCustomerByEmail` | `emailAddress` | Delete customer user account. Posts are reassigned to user ID 1 | | `deleteCustomerByEmail` | `emailAddress` | Delete customer user account. Posts are reassigned to user ID 1 |
| `resetSettingsGroupToDefault` | `settingsGroup` | Reset settings in settings group to default except `select` fields | | `resetSettingsGroupToDefault` | `settingsGroup` | Reset settings in settings group to default except `select` fields |

View File

@ -4,6 +4,7 @@ import {Coupon, Setting, SimpleProduct} from '@woocommerce/api';
const client = factories.api.withDefaultPermalinks; const client = factories.api.withDefaultPermalinks;
const onboardingProfileEndpoint = '/wc-admin/onboarding/profile'; const onboardingProfileEndpoint = '/wc-admin/onboarding/profile';
const shippingZoneEndpoint = '/wc/v3/shipping/zones'; const shippingZoneEndpoint = '/wc/v3/shipping/zones';
const shippingClassesEndpoint = '/wc/v3/products/shipping_classes';
const userEndpoint = '/wp/v2/users'; const userEndpoint = '/wp/v2/users';
/** /**
@ -99,6 +100,20 @@ export const withRestApi = {
} }
} }
}, },
/**
* Use api package to delete shipping classes.
*
* @return {Promise} Promise resolving once shipping classes have been deleted.
*/
deleteAllShippingClasses: async () => {
const shippingClasses = await client.get( shippingClassesEndpoint );
if ( shippingClasses.data && shippingClasses.data.length ) {
for ( let c = 0; c < shippingClasses.data.length; c++ ) {
const response = await client.delete( shippingClassesEndpoint + `/${shippingClasses.data[c].id}?force=true` );
expect( response.statusCode ).toBe( 200 );
}
}
},
/** /**
* Delete a customer account by their email address if the user exists. * Delete a customer account by their email address if the user exists.
* *