From 7a892f61d28f1c10ad198f3626bc12e5b0211958 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Wed, 3 Mar 2021 19:52:29 -0400 Subject: [PATCH 01/42] update shared objects among models - add optional defaultKey, defaultValue to meta data - move REST _links object to model shared - add _links collection to coupons --- tests/e2e/api/src/models/coupons/coupon.ts | 11 +++ .../src/models/products/abstract/common.ts | 8 +-- .../api/src/models/products/abstract/data.ts | 8 +-- .../api/src/models/products/shared/classes.ts | 56 --------------- .../e2e/api/src/models/products/variation.ts | 8 +-- tests/e2e/api/src/models/shared-types.ts | 70 +++++++++++++++++++ .../repositories/rest/coupons/transformer.ts | 1 + tests/e2e/api/src/repositories/rest/shared.ts | 7 ++ 8 files changed, 101 insertions(+), 68 deletions(-) diff --git a/tests/e2e/api/src/models/coupons/coupon.ts b/tests/e2e/api/src/models/coupons/coupon.ts index a0ee904de29..20e3f42ee9b 100644 --- a/tests/e2e/api/src/models/coupons/coupon.ts +++ b/tests/e2e/api/src/models/coupons/coupon.ts @@ -12,6 +12,7 @@ import { import { CouponUpdateParams, } from './shared'; +import { ObjectLinks } from '../shared-types'; /** * The parameters embedded in this generic can be used in the ModelRepository in order to give @@ -222,6 +223,16 @@ export class Coupon extends Model { */ public readonly usedBy: Array = []; + /** + * The coupon's links. + * + * @type {ReadonlyArray.} + */ + public readonly links: ObjectLinks = { + collection: [ { href: '' } ], + self: [ { href: '' } ], + }; + /** * Creates a new coupon instance with the given properties * diff --git a/tests/e2e/api/src/models/products/abstract/common.ts b/tests/e2e/api/src/models/products/abstract/common.ts index 88601fa6ad0..4f9833f8eab 100644 --- a/tests/e2e/api/src/models/products/abstract/common.ts +++ b/tests/e2e/api/src/models/products/abstract/common.ts @@ -3,9 +3,9 @@ import { ModelID } from '../../model'; import { CatalogVisibility, ProductTerm, - ProductLinks, ProductAttribute, } from '../shared'; +import { ObjectLinks } from '../../shared-types'; /** * The common parameters that all products can use in search. @@ -137,11 +137,11 @@ export abstract class AbstractProduct extends AbstractProductData { public readonly attributes: readonly ProductAttribute[] = []; /** - * The products links. + * The product's links. * - * @type {ReadonlyArray.} + * @type {ReadonlyArray.} */ - public readonly links: ProductLinks = { + public readonly links: ObjectLinks = { collection: [ { href: '' } ], self: [ { href: '' } ], }; diff --git a/tests/e2e/api/src/models/products/abstract/data.ts b/tests/e2e/api/src/models/products/abstract/data.ts index 0d1b83cb37e..e76c1c7d9d8 100644 --- a/tests/e2e/api/src/models/products/abstract/data.ts +++ b/tests/e2e/api/src/models/products/abstract/data.ts @@ -1,6 +1,6 @@ import { Model } from '../../model'; -import { MetaData, PostStatus } from '../../shared-types'; -import { ProductImage, ProductLinks } from '../shared'; +import { MetaData, PostStatus, ObjectLinks } from '../../shared-types'; +import { ProductImage } from '../shared'; /** * Base product data. @@ -93,9 +93,9 @@ export abstract class AbstractProductData extends Model { /** * The product data links. * - * @type {ReadonlyArray.} + * @type {ReadonlyArray.} */ - public readonly links: ProductLinks = { + public readonly links: ObjectLinks = { collection: [ { href: '' } ], self: [ { href: '' } ], }; diff --git a/tests/e2e/api/src/models/products/shared/classes.ts b/tests/e2e/api/src/models/products/shared/classes.ts index 7343c594352..c08e0a20b70 100644 --- a/tests/e2e/api/src/models/products/shared/classes.ts +++ b/tests/e2e/api/src/models/products/shared/classes.ts @@ -208,59 +208,3 @@ export class ProductImage { Object.assign( this, properties ); } } - -/** - * A product link item. - */ -class ProductLinkItem { - /** - * The options which are available for the attribute. - * - * @type {ReadonlyArray.} - */ - public readonly href: string = ''; - - /** - * Creates a new product link item. - * - * @param {Partial.} properties The properties to set. - */ - public constructor( properties?: Partial< ProductLinkItem > ) { - Object.assign( this, properties ); - } -} - -/** - * A product's links. - */ -export class ProductLinks { - /** - * The collection containing the product. - * - * @type {ReadonlyArray.} - */ - public readonly collection: readonly ProductLinkItem[] = []; - - /** - * Self referential link to the product. - * - * @type {ReadonlyArray.} - */ - public readonly self: readonly ProductLinkItem[] = []; - - /** - * The link to the parent. - * - * @type {ReadonlyArray.} - */ - public readonly up?: readonly ProductLinkItem[] = []; - - /** - * Creates a new product link list. - * - * @param {Partial.} properties The properties to set. - */ - public constructor( properties?: Partial< ProductLinks > ) { - Object.assign( this, properties ); - } -} diff --git a/tests/e2e/api/src/models/products/variation.ts b/tests/e2e/api/src/models/products/variation.ts index 78e8580c2fa..beb1bad8071 100644 --- a/tests/e2e/api/src/models/products/variation.ts +++ b/tests/e2e/api/src/models/products/variation.ts @@ -15,13 +15,13 @@ import { ProductPriceUpdateParams, ProductSalesTaxUpdateParams, ProductShippingUpdateParams, - ProductLinks, Taxability, ProductDownload, StockStatus, BackorderStatus, ProductDefaultAttribute, } from './shared'; +import { ObjectLinks } from '../shared-types'; import { CreatesChildModels, DeletesChildModels, @@ -149,11 +149,11 @@ export class ProductVariation extends AbstractProductData implements public readonly shippingClassId: number = 0; /** - * The variation links. + * The variation's links. * - * @type {ReadonlyArray.} + * @type {ReadonlyArray.} */ - public readonly links: ProductLinks = { + public readonly links: ObjectLinks = { collection: [ { href: '' } ], self: [ { href: '' } ], up: [ { href: '' } ], diff --git a/tests/e2e/api/src/models/shared-types.ts b/tests/e2e/api/src/models/shared-types.ts index 5f64fff0b72..d041f3c48c8 100644 --- a/tests/e2e/api/src/models/shared-types.ts +++ b/tests/e2e/api/src/models/shared-types.ts @@ -35,6 +35,20 @@ export class MetaData extends Model { */ public readonly value: any = ''; + /** + * The key of the metadata. + * + * @type {string} + */ + public readonly displayKey?: string = ''; + + /** + * The value of the metadata. + * + * @type {*} + */ + public readonly displayValue?: string = ''; + /** * Creates a new metadata. * @@ -45,3 +59,59 @@ export class MetaData extends Model { Object.assign( this, properties ); } } + +/** + * An object link item. + */ +class LinkItem { + /** + * The href of the link. + * + * @type {ReadonlyArray.} + */ + public readonly href: string = ''; + + /** + * Creates a new product link item. + * + * @param {Partial.} properties The properties to set. + */ + public constructor( properties?: Partial< LinkItem > ) { + Object.assign( this, properties ); + } +} + +/** + * An object's links. + */ +export class ObjectLinks { + /** + * The collection containing the object. + * + * @type {ReadonlyArray.} + */ + public readonly collection: readonly LinkItem[] = []; + + /** + * Self referential link to the object. + * + * @type {ReadonlyArray.} + */ + public readonly self: readonly LinkItem[] = []; + + /** + * The link to the parent object. + * + * @type {ReadonlyArray.} + */ + public readonly up?: readonly LinkItem[] = []; + + /** + * Creates a new product link list. + * + * @param {Partial.} properties The properties to set. + */ + public constructor( properties?: Partial< ObjectLinks > ) { + Object.assign( this, properties ); + } +} diff --git a/tests/e2e/api/src/repositories/rest/coupons/transformer.ts b/tests/e2e/api/src/repositories/rest/coupons/transformer.ts index b3827471242..8e0c7d85eb9 100644 --- a/tests/e2e/api/src/repositories/rest/coupons/transformer.ts +++ b/tests/e2e/api/src/repositories/rest/coupons/transformer.ts @@ -57,6 +57,7 @@ export function createCouponTransformer(): ModelTransformer< Coupon > { maximumAmount: 'maximum_amount', emailRestrictions: 'email_restrictions', usedBy: 'used_by', + links: '_links', }, ), ], diff --git a/tests/e2e/api/src/repositories/rest/shared.ts b/tests/e2e/api/src/repositories/rest/shared.ts index 1d52d73ec3d..3c4e976d177 100644 --- a/tests/e2e/api/src/repositories/rest/shared.ts +++ b/tests/e2e/api/src/repositories/rest/shared.ts @@ -16,6 +16,7 @@ import { CreateChildFn, ModelTransformer, IgnorePropertyTransformation, + KeyChangeTransformation, // @ts-ignore ModelParentID, } from '../../framework'; @@ -34,6 +35,12 @@ export function createMetaDataTransformer(): ModelTransformer< MetaData > { return new ModelTransformer( [ new IgnorePropertyTransformation( [ 'id' ] ), + new KeyChangeTransformation< MetaData >( + { + displayKey: 'display_key', + displayValue: 'display_value', + }, + ), ], ); } From 03c60b988b086b15e23e8760e9c67eb9a65a33b9 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Fri, 5 Mar 2021 10:39:35 -0400 Subject: [PATCH 02/42] add order classes --- tests/e2e/api/src/models/orders/index.ts | 1 + .../api/src/models/orders/shared/classes.ts | 412 ++++++++++++++++++ .../e2e/api/src/models/orders/shared/index.ts | 2 + .../e2e/api/src/models/orders/shared/types.ts | 3 + 4 files changed, 418 insertions(+) create mode 100644 tests/e2e/api/src/models/orders/index.ts create mode 100644 tests/e2e/api/src/models/orders/shared/classes.ts create mode 100644 tests/e2e/api/src/models/orders/shared/index.ts create mode 100644 tests/e2e/api/src/models/orders/shared/types.ts diff --git a/tests/e2e/api/src/models/orders/index.ts b/tests/e2e/api/src/models/orders/index.ts new file mode 100644 index 00000000000..c3da79f741b --- /dev/null +++ b/tests/e2e/api/src/models/orders/index.ts @@ -0,0 +1 @@ +export * from './shared'; diff --git a/tests/e2e/api/src/models/orders/shared/classes.ts b/tests/e2e/api/src/models/orders/shared/classes.ts new file mode 100644 index 00000000000..3852519b94c --- /dev/null +++ b/tests/e2e/api/src/models/orders/shared/classes.ts @@ -0,0 +1,412 @@ +import { MetaData } from '../../shared-types'; +import { Model } from '../../model'; +import { TaxStatus } from './types'; + +/** + * Order item meta. + */ +export class OrderItemMeta extends Model { + /** + * The meta data the order item. + * + * @type {ReadonlyArray.} + */ + public readonly metaData: MetaData[] = []; +} + +/** + * Order line item tax entry. + */ +export class OrderItemTax extends Model { + /** + * The total tax for this tax rate on this item. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The subtotal tax for this tax rate on this item. + * + * @type {string} + */ + public readonly subtotal: string = ''; +} + +/** + * An order address. + */ +export class OrderAddress { + /** + * The first name of the person in the address. + * + * @type {string} + */ + public readonly firstName: string = ''; + + /** + * The last name of the person in the address. + * + * @type {string} + */ + public readonly lastName: string = ''; + + /** + * The company name of the person in the address. + * + * @type {string} + */ + public readonly companyName: string = ''; + + /** + * The first address line in the address. + * + * @type {string} + */ + public readonly address1: string = ''; + + /** + * The second address line in the address. + * + * @type {string} + */ + public readonly address2: string = ''; + + /** + * The city in the address. + * + * @type {string} + */ + public readonly city: string = ''; + + /** + * The state in the address. + * + * @type {string} + */ + public readonly state: string = ''; + + /** + * The postal code in the address. + * + * @type {string} + */ + public readonly postCode: string = ''; + + /** + * The country code for the address. + * + * @type {string} + */ + public readonly countryCode: string = ''; + + /** + * The email address of the person in the address. + * + * @type {string} + */ + public readonly email: string = ''; + + /** + * The phone number of the person in the address. + * + * @type {string} + */ + public readonly phone: string = ''; +} + +/** + * Order Line Item + */ +export class OrderLineItem extends OrderItemMeta { + /** + * The name of the product. + * + * @type {string} + */ + public readonly name: string = ''; + + /** + * The ID of the product. + * + * @type {number} + */ + public readonly ProductId: number = -1; + + /** + * The ID of the product variation. + * + * @type {number} + */ + public readonly variationId: number = 0; + + /** + * The quantity of the product. + * + * @type {number} + */ + public readonly quantity: number = -1; + + /** + * The tax class for the product. + * + * @type {string} + */ + public readonly taxClass: string = ''; + + /** + * The subtotal for the product. + * + * @type {string} + */ + public readonly subtotal: string = ''; + + /** + * The subtotal tax for the product. + * + * @type {string} + */ + public readonly subtotalTax: string = ''; + + /** + * The total for the product including adjusments. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The total tax for the product including adjusments. + * + * @type {string} + */ + public readonly totalTax: string = ''; + + /** + * The taxes applied to the product. + * + * @type {ReadonlyArray.} + */ + public readonly taxes: OrderItemTax[] = []; + + /** + * The product SKU. + * + * @type {string} + */ + public readonly sku: string = ''; + + /** + * The price of the product. + * + * @type {number} + */ + public readonly price: number = -1; + + /** + * The name of the parent product. + * + * @type {string|null} + */ + public readonly parentName: string | null = null; +} + +/** + * Order Tax Rate + */ +export class OrderTaxRate extends Model { + /** + * The tax rate code. + * + * @type {string} + */ + public readonly rateCode: string = ''; + + /** + * The tax rate id. + * + * @type {number} + */ + public readonly rateId: number = 0; + + /** + * The tax label. + * + * @type {string} + */ + public readonly label: string = ''; + + /** + * Flag indicating whether it's a compound tax rate. + * + * @type {boolean} + */ + public readonly compoundRate: boolean = false; + + /** + * The total tax for this rate code. + * + * @type {string} + */ + public readonly taxTotal: string = ''; + + /** + * The total shipping tax for this rate code. + * + * @type {string} + */ + public readonly shippingTaxTotal: string = ''; + + /** + * The tax rate as a percentage. + * + * @type {number} + */ + public readonly ratePercent: number = 0; +} + +/** + * Order shipping line + */ +export class OrderShippingLine extends OrderItemMeta { + /** + * The shipping method title. + * + * @type {string} + */ + public readonly methodTitle: string = ''; + + /** + * The shipping method id. + * + * @type {string} + */ + public readonly methodId: string = ''; + + /** + * The shipping method instance id. + * + * @type {string} + */ + public readonly instanceId: string = ''; + + /** + * The total shipping amount for this method. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The total tax amount for this shipping method. + * + * @type {string} + */ + public readonly totalTax: string = ''; + + /** + * The taxes applied to this shipping method. + * + * @type {ReadonlyArray.} + */ + public readonly taxes: OrderItemTax[] = []; +} + +/** + * Order fee line + */ +export class OrderFeeLine extends OrderItemMeta { + /** + * The name of the fee. + * + * @type {string} + */ + public readonly name: string = ''; + + /** + * The tax class of the fee. + * + * @type {string} + */ + public readonly taxClass: string = ''; + + /** + * The tax status of the fee. + * + * @type {TaxStatus} + */ + public readonly taxStatus: TaxStatus = ''; + + /** + * The total amount for this fee. + * + * @type {string} + */ + public readonly amount: string = ''; + + /** + * The display total amount for this fee. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The total tax amount for this fee. + * + * @type {string} + */ + public readonly totalTax: string = ''; + + /** + * The taxes applied to this fee. + * + * @type {ReadonlyArray.} + */ + public readonly taxes: OrderItemTax[] = []; +} + +/** + * Order coupon line + */ +export class OrderCouponLine extends OrderItemMeta { + /** + * The coupon code + * + * @type {string} + */ + public readonly code: string = ''; + + /** + * The discount amount. + * + * @type {string} + */ + public readonly discount: string = ''; + + /** + * The discount tax. + * + * @type {string} + */ + public readonly discountTax: string = ''; +} + +/** + * Order refund line + */ +export class OrderRefundLine extends Model { + /** + * The reason for giving the refund. + * + * @type {string} + */ + public readonly reason: string = ''; + + /** + * The total amount of the refund. + * + * @type {string} + */ + public readonly total: string = ''; +} diff --git a/tests/e2e/api/src/models/orders/shared/index.ts b/tests/e2e/api/src/models/orders/shared/index.ts new file mode 100644 index 00000000000..15eb796c953 --- /dev/null +++ b/tests/e2e/api/src/models/orders/shared/index.ts @@ -0,0 +1,2 @@ +export * from './classes'; +export * from './types'; diff --git a/tests/e2e/api/src/models/orders/shared/types.ts b/tests/e2e/api/src/models/orders/shared/types.ts new file mode 100644 index 00000000000..4e987c99d24 --- /dev/null +++ b/tests/e2e/api/src/models/orders/shared/types.ts @@ -0,0 +1,3 @@ + +//@todo: complete this type +export type TaxStatus = 'taxable' | string; From b05a97e2c069f3dffbc23e576bbd9529eb729343 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Sun, 7 Mar 2021 23:06:48 -0400 Subject: [PATCH 03/42] add order types --- .../e2e/api/src/models/orders/shared/types.ts | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/tests/e2e/api/src/models/orders/shared/types.ts b/tests/e2e/api/src/models/orders/shared/types.ts index 4e987c99d24..adeba0128c4 100644 --- a/tests/e2e/api/src/models/orders/shared/types.ts +++ b/tests/e2e/api/src/models/orders/shared/types.ts @@ -1,3 +1,66 @@ +/** + * An order's status. + * + * @typedef OrderStatus + */ +export type OrderStatus = 'pending' | 'processing' | 'complete' | 'on-hold' | 'refunded' + | 'cancelled' | 'failed' | 'trash' | string; -//@todo: complete this type -export type TaxStatus = 'taxable' | string; +/** + * An fee's tax status. + * + * @typedef TaxStatus + */ +export type TaxStatus = 'taxable' | 'none'; + +/** + * Base order properties + */ +export type OrderDataUpdateParams = 'id' | 'parentId' | 'status' | 'currency' | 'version' + | 'pricesIncludeTax' | 'discountTotal' | 'discountTax' | 'shippingTotal' | 'shippingTax' + | 'cartTax' | 'customerId' | 'orderKey' | 'paymentMethod' | 'paymentMethodTitle' + | 'transactionId' | 'customerIpAddress' | 'customerUserAgent' | 'createdVia' | 'datePaid' + | 'customerNote' | 'dateCompleted' | 'cartHash' | 'orderNumber' | 'currencySymbol'; + +/** + * Common total properties + */ +export type OrderTotalUpdateParams = 'total' | 'totalTax'; + +/** + * Order address properties + */ +export type OrderAddressUpdateParams = 'firstName' | 'lastName' | 'companyName' | 'address1' + | 'address2' | 'city' | 'state' | 'postCode' | 'countryCode' | 'email' | 'phone'; + +/** + * Line item properties + */ +export type OrderLineItemUpdateParams = 'name' | 'ProductId' | 'variationId' | 'quantity' + | 'taxClass' | 'subtotal' | 'subtotalTax' | 'sku' | 'price' | 'parentName'; + +/** + * Tax rate properties + */ +export type OrderTaxUpdateParams = 'rateCode' | 'rateId' | 'label' | 'compoundRate' + | 'taxTotal' | 'shippingTaxTotal' | 'ratePercent'; + +/** + * Order shipping properties + */ +export type OrderShippingUpdateParams = 'methodTitle' | 'methodId' | 'instanceId'; + +/** + * Order fee properties + */ +export type OrderFeeUpdateParams = 'name' | 'taxClass' | 'taxStatus' | 'amount'; + +/** + * Order coupon properties + */ +export type OrderCouponUpdateParams = 'code' | 'discount' | 'discountTax'; + +/** + * Order refund properties + */ +export type OrderRefundUpdateParams = 'reason' | 'total'; From 1664ece7eb3ff04a76ad97d53b579772768d013a Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Mon, 8 Mar 2021 09:59:46 -0400 Subject: [PATCH 04/42] use valid tax status on fees --- tests/e2e/api/src/models/orders/shared/classes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/api/src/models/orders/shared/classes.ts b/tests/e2e/api/src/models/orders/shared/classes.ts index 3852519b94c..c506f6563cc 100644 --- a/tests/e2e/api/src/models/orders/shared/classes.ts +++ b/tests/e2e/api/src/models/orders/shared/classes.ts @@ -335,7 +335,7 @@ export class OrderFeeLine extends OrderItemMeta { * * @type {TaxStatus} */ - public readonly taxStatus: TaxStatus = ''; + public readonly taxStatus: TaxStatus = 'taxable'; /** * The total amount for this fee. From 1cda09d2607e46004d0e1a9a988db4d0bfcbe741 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Tue, 9 Mar 2021 11:33:29 -0400 Subject: [PATCH 05/42] fix api package build errors --- tests/e2e/api/src/framework/model-repository.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/e2e/api/src/framework/model-repository.ts b/tests/e2e/api/src/framework/model-repository.ts index ca598404b93..9c30993a83a 100644 --- a/tests/e2e/api/src/framework/model-repository.ts +++ b/tests/e2e/api/src/framework/model-repository.ts @@ -401,7 +401,7 @@ export class ModelRepository< T extends ModelRepositoryParams > implements } return ( this.listHook as ListChildFn< T > )( - paramsOrParent as ParentID< T >, + ( paramsOrParent as unknown ) as ParentID< T >, params, ); } @@ -428,7 +428,7 @@ export class ModelRepository< T extends ModelRepositoryParams > implements } return ( this.createHook as CreateChildFn< T > )( - propertiesOrParent as ParentID, + ( propertiesOrParent as unknown ) as ParentID, properties as Partial< ModelClass >, ); } @@ -455,7 +455,7 @@ export class ModelRepository< T extends ModelRepositoryParams > implements } return ( this.readHook as ReadChildFn< T > )( - idOrParent as ParentID< T >, + ( idOrParent as unknown ) as ParentID< T >, childID, ); } @@ -480,14 +480,14 @@ export class ModelRepository< T extends ModelRepositoryParams > implements if ( properties === undefined ) { return ( this.updateHook as UpdateFn< T > )( idOrParent as ModelID, - propertiesOrChildID as UpdateParams< T >, + ( propertiesOrChildID as unknown ) as UpdateParams< T >, ); } return ( this.updateHook as UpdateChildFn< T > )( - idOrParent as ParentID< T >, + ( idOrParent as unknown ) as ParentID< T >, propertiesOrChildID as ModelID, - properties, + ( properties as unknown ) as UpdateParams< T >, ); } @@ -513,7 +513,7 @@ export class ModelRepository< T extends ModelRepositoryParams > implements } return ( this.deleteHook as DeleteChildFn< T > )( - idOrParent as ParentID< T >, + ( idOrParent as unknown ) as ParentID< T >, childID, ); } From 2c1b3b52a91267b45641c5325cc0b3d8961661d0 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 11 Mar 2021 09:20:26 -0400 Subject: [PATCH 06/42] add order class and repository --- tests/e2e/api/src/models/orders/index.ts | 1 + tests/e2e/api/src/models/orders/orders.ts | 364 ++++++++++++++++++ .../api/src/models/orders/shared/classes.ts | 4 +- 3 files changed, 367 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/api/src/models/orders/orders.ts diff --git a/tests/e2e/api/src/models/orders/index.ts b/tests/e2e/api/src/models/orders/index.ts index c3da79f741b..de526a0af64 100644 --- a/tests/e2e/api/src/models/orders/index.ts +++ b/tests/e2e/api/src/models/orders/index.ts @@ -1 +1,2 @@ export * from './shared'; +export * from './orders'; diff --git a/tests/e2e/api/src/models/orders/orders.ts b/tests/e2e/api/src/models/orders/orders.ts new file mode 100644 index 00000000000..04fd8a93282 --- /dev/null +++ b/tests/e2e/api/src/models/orders/orders.ts @@ -0,0 +1,364 @@ +//import { HTTPClient } from '../../http'; +//import { orderRESTRepository } from '../../repositories'; +import { + ModelRepositoryParams, + CreatesModels, + ListsModels, + ReadsModels, + UpdatesModels, + DeletesModels, +} from '../../framework'; +import { + OrderAddressUpdateParams, + OrderCouponUpdateParams, + OrderDataUpdateParams, + OrderFeeUpdateParams, + OrderLineItemUpdateParams, + OrderRefundUpdateParams, + OrderShippingUpdateParams, + OrderTaxUpdateParams, + OrderTotalUpdateParams, + OrderItemMeta, + OrderAddress, + OrderCouponLine, + OrderFeeLine, + OrderLineItem, + OrderRefundLine, + OrderShippingLine, + OrderStatus, + OrderTaxRate, +} from './shared'; +import { ObjectLinks } from '../shared-types'; + +/** + * The parameters that orders can update. + */ +type OrderUpdateParams = OrderAddressUpdateParams + & OrderCouponUpdateParams + & OrderDataUpdateParams + & OrderFeeUpdateParams + & OrderLineItemUpdateParams + & OrderRefundUpdateParams + & OrderShippingUpdateParams + & OrderTaxUpdateParams + & OrderTotalUpdateParams; + +/** + * The parameters embedded in this generic can be used in the ModelRepository in order to give + * type-safety in an incredibly granular way. + */ +export type OrderRepositoryParams = ModelRepositoryParams< Order, never, never, OrderUpdateParams >; + +/** + * An interface for creating coupons using the repository. + * + * @typedef CreatesCoupons + * @alias CreatesModels. + */ +export type CreatesCoupons = CreatesModels< OrderRepositoryParams >; + +/** + * An interface for reading coupons using the repository. + * + * @typedef ReadsCoupons + * @alias ReadsModels. + */ +export type ReadsCoupons = ReadsModels< OrderRepositoryParams >; + +/** + * An interface for updating coupons using the repository. + * + * @typedef UpdatesCoupons + * @alias UpdatesModels. + */ +export type UpdatesCoupons = UpdatesModels< OrderRepositoryParams >; + +/** + * An interface for listing coupons using the repository. + * + * @typedef ListsCoupons + * @alias ListsModels. + */ +export type ListsCoupons = ListsModels< OrderRepositoryParams >; + +/** + * An interface for deleting coupons using the repository. + * + * @typedef DeletesCoupons + * @alias DeletesModels. + */ +export type DeletesCoupons = DeletesModels< OrderRepositoryParams >; + +/** + * A coupon object. + */ +export class Order extends OrderItemMeta { + /** + * The parent order id. + * + * @type {number} + */ + public readonly parentId: number = 0; + + /** + * The order status. + * + * @type {string} + */ + public readonly status: OrderStatus = ''; + + /** + * The order currency. + * + * @type {string} + */ + public readonly currency: string = ''; + + /** + * The WC version used to create the order. + * + * @type {string} + */ + public readonly version: string = ''; + + /** + * Flags if the prices include tax. + * + * @type {boolean} + */ + public readonly pricesIncludeTax: boolean = false; + + /** + * The total of the discounts on the order. + * + * @type {string} + */ + public readonly discountTotal: string = ''; + + /** + * The total of the tax on discounts on the order. + * + * @type {string} + */ + public readonly discountTax: string = ''; + + /** + * The total of the shipping on the order. + * + * @type {string} + */ + public readonly shippingTotal: string = ''; + + /** + * The total of the tax on shipping on the order. + * + * @type {string} + */ + public readonly shippingTax: string = ''; + + /** + * The total cart tax on the order. + * + * @type {string} + */ + public readonly cartTax: string = ''; + + /** + * The total for the order including adjustments. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The total tax for the order including adjustments. + * + * @type {string} + */ + public readonly totalTax: string = ''; + + /** + * The customer id. + * + * @type {number} + */ + public readonly customerId: number = 0; + + /** + * A unique key assigned to the order. + * + * @type {string} + */ + public readonly orderKey: string = ''; + + /** + * The billing address. + * + * @type {OrderAddress} + */ + public readonly billing: OrderAddress | null = null; + + /** + * The shipping address. + * + * @type {OrderAddress} + */ + public readonly shipping: OrderAddress | null = null; + + /** + * Name of the payment method. + * + * @type {string} + */ + public readonly paymentMethod: string = ''; + + /** + * Title of the payment method + * + * @type {string} + */ + public readonly paymentMethodTitle: string = ''; + + /** + * Payment transaction ID. + * + * @type {string} + */ + public readonly transactionId: string = ''; + + /** + * Customer IP address. + * + * @type {string} + */ + public readonly customerIpAddress: string = ''; + + /** + * Customer web browser user agent. + * + * @type {string} + */ + public readonly customerUserAgent: string = ''; + + /** + * Method used to create the order. + * + * @type {string} + */ + public readonly createdVia: string = ''; + + /** + * Customer note. + * + * @type {string} + */ + public readonly customerNote: string = ''; + + /** + * Date the order was completed. + * + * @type {string} + */ + public readonly dateCompleted: Date | null = null; + + /** + * Date the order was paid. + * + * @type {string} + */ + public readonly datePaid: Date | null = null; + + /** + * Hash of the cart's contents. + * + * @type {string} + */ + public readonly cartHash: string = ''; + + /** + * Number assigned to the order. + * + * @type {string} + */ + public readonly orderNumber: string = ''; + + /** + * Currency symbol for the order. + * + * @type {string} + */ + public readonly currencySymbol: string = ''; + + /** + * The order's line items. + * + * @type {ReadonlyArray.} + */ + public readonly lineItems: OrderLineItem[] = []; + + /** + * The order's tax rates. + * + * @type {ReadonlyArray.} + */ + public readonly taxLines: OrderTaxRate[] = []; + + /** + * The order's shipping charges. + * + * @type {ReadonlyArray.} + */ + public readonly shippingLines: OrderShippingLine[] = []; + + /** + * The order's fees. + * + * @type {ReadonlyArray.} + */ + public readonly feeLines: OrderFeeLine[] = []; + + /** + * The coupons used on the order. + * + * @type {ReadonlyArray.} + */ + public readonly couponLines: OrderCouponLine[] = []; + + /** + * The refunds to the order. + * + * @type {ReadonlyArray.} + */ + public readonly refunds: OrderRefundLine[] = []; + + /** + * The order's links. + * + * @type {ReadonlyArray.} + */ + public readonly links: ObjectLinks = { + collection: [ { href: '' } ], + self: [ { href: '' } ], + }; + + /** + * Creates a new coupon instance with the given properties + * + * @param {Object} properties The properties to set in the object. + */ + public constructor( properties?: Partial< Order > ) { + super(); + Object.assign( this, properties ); + } + /* + /** + * Returns the repository for interacting with this type of model. + * + * @param {HTTPClient} httpClient The client for communicating via HTTP. + */ + /* + public static restRepository( httpClient: HTTPClient ): ReturnType< typeof orderRESTRepository > { + return orderRESTRepository( httpClient ); + } + */ +} diff --git a/tests/e2e/api/src/models/orders/shared/classes.ts b/tests/e2e/api/src/models/orders/shared/classes.ts index c506f6563cc..f26923edcd5 100644 --- a/tests/e2e/api/src/models/orders/shared/classes.ts +++ b/tests/e2e/api/src/models/orders/shared/classes.ts @@ -169,14 +169,14 @@ export class OrderLineItem extends OrderItemMeta { public readonly subtotalTax: string = ''; /** - * The total for the product including adjusments. + * The total for the product including adjustments. * * @type {string} */ public readonly total: string = ''; /** - * The total tax for the product including adjusments. + * The total tax for the product including adjustments. * * @type {string} */ From e1c6c540d72ad3de6a0f0116ca8d6064d7f3ed15 Mon Sep 17 00:00:00 2001 From: roykho Date: Fri, 9 Apr 2021 05:33:06 -0700 Subject: [PATCH 07/42] Convert notices to use native nonce generation from WC Admin --- includes/admin/class-wc-admin-notices.php | 45 ------------------- .../notes/class-wc-notes-run-db-update.php | 41 ++++++++++------- includes/class-woocommerce.php | 1 - 3 files changed, 24 insertions(+), 63 deletions(-) diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index fa9716cc498..70c76ee6120 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -64,51 +64,6 @@ class WC_Admin_Notices { } } - /** - * Parses query to create nonces when available. - * - * @param object $response The WP_REST_Response we're working with. - * @return object $response The prepared WP_REST_Response object. - */ - public static function prepare_note_with_nonce( $response ) { - if ( 'wc-update-db-reminder' !== $response->data['name'] || ! isset( $response->data['actions'] ) ) { - return $response; - } - - foreach ( $response->data['actions'] as $action_key => $action ) { - $url_parts = ! empty( $action->query ) ? wp_parse_url( $action->query ) : ''; - - if ( ! isset( $url_parts['query'] ) ) { - continue; - } - - wp_parse_str( $url_parts['query'], $params ); - - if ( array_key_exists( '_nonce_action', $params ) && array_key_exists( '_nonce_name', $params ) ) { - $org_params = $params; - - // Check to make sure we're acting on the whitelisted nonce actions. - if ( 'wc_db_update' !== $params['_nonce_action'] && 'woocommerce_hide_notices_nonce' !== $params['_nonce_action'] ) { - continue; - } - - unset( $org_params['_nonce_action'] ); - unset( $org_params['_nonce_name'] ); - - $url = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path']; - - $nonce = array( $params['_nonce_name'] => wp_create_nonce( $params['_nonce_action'] ) ); - $merged_params = array_merge( $nonce, $org_params ); - $parsed_query = add_query_arg( $merged_params, $url ); - - $response->data['actions'][ $action_key ]->query = $parsed_query; - $response->data['actions'][ $action_key ]->url = $parsed_query; - } - } - - return $response; - } - /** * Store notices to DB */ diff --git a/includes/admin/notes/class-wc-notes-run-db-update.php b/includes/admin/notes/class-wc-notes-run-db-update.php index 1fad100ff9e..77017ec2ca2 100644 --- a/includes/admin/notes/class-wc-notes-run-db-update.php +++ b/includes/admin/notes/class-wc-notes-run-db-update.php @@ -109,24 +109,23 @@ class WC_Notes_Run_Db_Update { * @return int Created/Updated note id */ private static function update_needed_notice( $note_id = null ) { - $update_url = html_entity_decode( + $update_url = add_query_arg( array( 'do_update_woocommerce' => 'true', - '_nonce_action' => 'wc_db_update', - '_nonce_name' => 'wc_db_update_nonce', ), wc_get_current_admin_url() ? wc_get_current_admin_url() : admin_url( 'admin.php?page=wc-settings' ) - ) - ); + ); $note_actions = array( array( - 'name' => 'update-db_run', - 'label' => __( 'Update WooCommerce Database', 'woocommerce' ), - 'url' => $update_url, - 'status' => 'unactioned', - 'primary' => true, + 'name' => 'update-db_run', + 'label' => __( 'Update WooCommerce Database', 'woocommerce' ), + 'url' => $update_url, + 'status' => 'unactioned', + 'primary' => true, + 'nonce_action' => 'wc_db_update', + 'nonce_name' => 'wc_db_update_nonce', ), array( 'name' => 'update-db_learn-more', @@ -166,6 +165,10 @@ class WC_Notes_Run_Db_Update { $note->clear_actions(); foreach ( $note_actions as $note_action ) { $note->add_action( ...array_values( $note_action ) ); + + if ( isset( $note_action['nonce_action'] ) ) { + $note->add_nonce_to_action( $note_action['name'], $note_action['nonce_action'], $note_action['nonce_name'] ); + } } return $note->save(); @@ -212,8 +215,6 @@ class WC_Notes_Run_Db_Update { add_query_arg( array( 'wc-hide-notice' => 'update', - '_nonce_action' => 'woocommerce_hide_notices_nonce', - '_nonce_name' => '_wc_notice_nonce', ), wc_get_current_admin_url() ? remove_query_arg( 'do_update_woocommerce', wc_get_current_admin_url() ) : admin_url( 'admin.php?page=wc-settings' ) ) @@ -221,11 +222,13 @@ class WC_Notes_Run_Db_Update { $note_actions = array( array( - 'name' => 'update-db_done', - 'label' => __( 'Thanks!', 'woocommerce' ), - 'url' => $hide_notices_url, - 'status' => 'actioned', - 'primary' => true, + 'name' => 'update-db_done', + 'label' => __( 'Thanks!', 'woocommerce' ), + 'url' => $hide_notices_url, + 'status' => 'actioned', + 'primary' => true, + 'nonce_action' => 'woocommerce_hide_notices_nonce', + 'nonce_name' => '_wc_notice_nonce', ), ); @@ -242,6 +245,10 @@ class WC_Notes_Run_Db_Update { $note->clear_actions(); foreach ( $note_actions as $note_action ) { $note->add_action( ...array_values( $note_action ) ); + + if ( isset( $note_action['nonce_action'] ) ) { + $note->add_nonce_to_action( $note_action['name'], $note_action['nonce_action'], $note_action['nonce_name'] ); + } } $note->save(); diff --git a/includes/class-woocommerce.php b/includes/class-woocommerce.php index be2df455f7d..b25315cbcf6 100644 --- a/includes/class-woocommerce.php +++ b/includes/class-woocommerce.php @@ -203,7 +203,6 @@ final class WooCommerce { add_action( 'switch_blog', array( $this, 'wpdb_table_fix' ), 0 ); add_action( 'activated_plugin', array( $this, 'activated_plugin' ) ); add_action( 'deactivated_plugin', array( $this, 'deactivated_plugin' ) ); - add_filter( 'woocommerce_rest_prepare_note', array( 'WC_Admin_Notices', 'prepare_note_with_nonce' ) ); // These classes set up hooks on instantiation. wc_get_container()->get( DownloadPermissionsAdjuster::class ); From 6ed847a7b9fa1f30442281d0e50bfc81aa6f799a Mon Sep 17 00:00:00 2001 From: roykho Date: Tue, 13 Apr 2021 19:53:00 -0700 Subject: [PATCH 08/42] Deprecate method instead of removing it --- includes/admin/class-wc-admin-notices.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index 70c76ee6120..b543c698472 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -64,6 +64,19 @@ class WC_Admin_Notices { } } + /** + * Parses query to create nonces when available. + * + * @deprecated 5.4.0 + * @param object $response The WP_REST_Response we're working with. + * @return object $response The prepared WP_REST_Response object. + */ + public static function prepare_note_with_nonce( $response ) { + wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '5.4.0' ); + + return $response; + } + /** * Store notices to DB */ From 5c07f8e7e1f1d6b03e6e8dba725432dd88d6d4dd Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Mon, 19 Apr 2021 17:06:59 +0200 Subject: [PATCH 09/42] Sort country codes alphabetically Sort country codes alphabetically to make finding them easier. --- includes/class-wc-countries.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/includes/class-wc-countries.php b/includes/class-wc-countries.php index 064f035cabc..e20d1358b27 100644 --- a/includes/class-wc-countries.php +++ b/includes/class-wc-countries.php @@ -365,7 +365,7 @@ class WC_Countries { * @return string[] */ public function get_european_union_countries( $type = '' ) { - $countries = array( 'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HU', 'HR', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK' ); + $countries = array( 'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK' ); if ( 'eu_vat' === $type ) { $countries[] = 'MC'; @@ -383,7 +383,7 @@ class WC_Countries { */ public function countries_using_vat() { wc_deprecated_function( 'countries_using_vat', '4.0', 'WC_Countries::get_vat_countries' ); - $countries = array( 'AL', 'AR', 'AZ', 'BS', 'BH', 'BY', 'BB', 'BO', 'EG', 'ET', 'CL', 'CO', 'EC', 'SV', 'FJ', 'GM', 'GH', 'GT', 'IN', 'IR', 'IL', 'KZ', 'MU', 'MK', 'MX', 'MD', 'MN', 'ME', 'NA', 'NP', 'NG', 'PS', 'PY', 'RU', 'RW', 'KN', 'SA', 'RS', 'ZA', 'KR', 'LK', 'TH', 'TR', 'UA', 'UY', 'UZ', 'VE', 'VN', 'AE' ); + $countries = array( 'AE', 'AL', 'AR', 'AZ', 'BB', 'BH', 'BO', 'BS', 'BY', 'CL', 'CO', 'EC', 'EG', 'ET', 'FJ', 'GH', 'GM', 'GT', 'IL', 'IN', 'IR', 'KN', 'KR', 'KZ', 'LK', 'MD', 'ME', 'MK', 'MN', 'MU', 'MX', 'NA', 'NG', 'NP', 'PS', 'PY', 'RS', 'RU', 'RW', 'SA', 'SV', 'TH', 'TR', 'UA', 'UY', 'UZ', 'VE', 'VN', 'ZA' ); return apply_filters( 'woocommerce_countries_using_vat', $countries ); } @@ -409,7 +409,7 @@ class WC_Countries { */ public function shipping_to_prefix( $country_code = '' ) { $country_code = $country_code ? $country_code : WC()->customer->get_shipping_country(); - $countries = array( 'GB', 'US', 'AE', 'CZ', 'DO', 'NL', 'PH', 'USAF' ); + $countries = array( 'AE', 'CZ', 'DO', 'GB', 'NL', 'PH', 'US', 'USAF' ); $return = in_array( $country_code, $countries, true ) ? __( 'to the', 'woocommerce' ) : __( 'to', 'woocommerce' ); return apply_filters( 'woocommerce_countries_shipping_to_prefix', $return, $country_code ); @@ -423,7 +423,7 @@ class WC_Countries { */ public function estimated_for_prefix( $country_code = '' ) { $country_code = $country_code ? $country_code : $this->get_base_country(); - $countries = array( 'GB', 'US', 'AE', 'CZ', 'DO', 'NL', 'PH', 'USAF' ); + $countries = array( 'AE', 'CZ', 'DO', 'GB', 'NL', 'PH', 'US', 'USAF' ); $return = in_array( $country_code, $countries, true ) ? __( 'the', 'woocommerce' ) . ' ' : ''; return apply_filters( 'woocommerce_countries_estimated_for_prefix', $return, $country_code ); @@ -510,8 +510,8 @@ class WC_Countries { 'woocommerce_localisation_address_formats', array( 'default' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}", - 'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}", 'AT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}", 'BE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state_code} {postcode}\n{country}", 'CH' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", @@ -519,9 +519,10 @@ class WC_Countries { 'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}", 'CZ' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'DE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", - 'EE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", - 'FI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'DK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'EE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}", + 'FI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}", 'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}", 'HU' => "{last_name} {first_name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}", @@ -530,20 +531,19 @@ class WC_Countries { 'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}", 'JM' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode_upper}\n{country}", 'JP' => "{postcode}\n{state} {city} {address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n{country}", - 'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}", 'LI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'NL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", - 'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}", 'NO' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}", 'PL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'PR' => "{company}\n{name}\n{address_1} {address_2}\n{city} \n{country} {postcode}", 'PT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", - 'SK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'RS' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", - 'SI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", - 'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}", 'SE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'SI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", + 'SK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}", 'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}", + 'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}", 'UG' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}, {country}", 'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}", 'VN' => "{name}\n{company}\n{address_1}\n{city}\n{country}", From 44493149d50a9e2cd2c62d10715b1aa3f492c79e Mon Sep 17 00:00:00 2001 From: gilesholder <40209785+gilesholder@users.noreply.github.com> Date: Wed, 28 Apr 2021 12:36:45 +0100 Subject: [PATCH 10/42] Update settings-paypal.php Makes IPN notification title consistent with the other titles (no capital letter starts on new words) --- includes/gateways/paypal/includes/settings-paypal.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/gateways/paypal/includes/settings-paypal.php b/includes/gateways/paypal/includes/settings-paypal.php index d9d56ddaadf..53729429e8e 100644 --- a/includes/gateways/paypal/includes/settings-paypal.php +++ b/includes/gateways/paypal/includes/settings-paypal.php @@ -58,7 +58,7 @@ return array( 'description' => sprintf( __( 'Log PayPal events, such as IPN requests, inside %s Note: this may log personal information. We recommend using this for debugging purposes only and deleting the logs when finished.', 'woocommerce' ), '' . WC_Log_Handler_File::get_log_file_path( 'paypal' ) . '' ), ), 'ipn_notification' => array( - 'title' => __( 'IPN Email Notifications', 'woocommerce' ), + 'title' => __( 'IPN email notifications', 'woocommerce' ), 'type' => 'checkbox', 'label' => __( 'Enable IPN email notifications', 'woocommerce' ), 'default' => 'yes', From a1be8f996979e2ab0c2db56a6e4ae584fda13813 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 29 Apr 2021 14:10:50 -0300 Subject: [PATCH 11/42] WIP orders rest repository --- .../api/src/repositories/rest/orders/index.ts | 0 .../api/src/repositories/rest/orders/order.ts | 0 .../repositories/rest/orders/transformer.ts | 24 +++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 tests/e2e/api/src/repositories/rest/orders/index.ts create mode 100644 tests/e2e/api/src/repositories/rest/orders/order.ts create mode 100644 tests/e2e/api/src/repositories/rest/orders/transformer.ts diff --git a/tests/e2e/api/src/repositories/rest/orders/index.ts b/tests/e2e/api/src/repositories/rest/orders/index.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/e2e/api/src/repositories/rest/orders/order.ts b/tests/e2e/api/src/repositories/rest/orders/order.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/e2e/api/src/repositories/rest/orders/transformer.ts b/tests/e2e/api/src/repositories/rest/orders/transformer.ts new file mode 100644 index 00000000000..41452a2ce26 --- /dev/null +++ b/tests/e2e/api/src/repositories/rest/orders/transformer.ts @@ -0,0 +1,24 @@ +import { + AddPropertyTransformation, + CustomTransformation, + IgnorePropertyTransformation, + KeyChangeTransformation, + ModelTransformation, + ModelTransformer, + ModelTransformerTransformation, + PropertyType, + PropertyTypeTransformation, + TransformationOrder, +} from '../../../framework'; +import { + OrderAddress, + OrderCouponLine, + OrderFeeLine, + OrderItemTax, + OrderLineItem, + OrderRefundLine, + OrderShippingLine, + OrderStatus, + OrderTaxRate, +} from '../../../models'; +import { createMetaDataTransformer } from '../shared'; From c354a672923ccc51d4a12ecb11eb86480d12f1a0 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 3 May 2021 20:21:00 -0600 Subject: [PATCH 12/42] Finish work on order; removed unused variable from test --- tests/e2e/api/src/models/index.ts | 1 + tests/e2e/api/src/models/orders/index.ts | 2 +- tests/e2e/api/src/models/orders/orders.ts | 59 ++-- .../api/src/models/orders/shared/classes.ts | 4 +- tests/e2e/api/src/repositories/rest/index.ts | 5 +- .../api/src/repositories/rest/orders/index.ts | 3 + .../api/src/repositories/rest/orders/order.ts | 47 +++ .../repositories/rest/orders/transformer.ts | 267 +++++++++++++++++- tests/e2e/config/default.json | 11 + tests/e2e/core-tests/specs/api/order.test.js | 82 ++++++ tests/e2e/core-tests/specs/index.js | 3 + .../merchant/wp-admin-order-emails.test.js | 1 - tests/e2e/specs/rest-api/order.js | 6 + 13 files changed, 451 insertions(+), 40 deletions(-) create mode 100644 tests/e2e/core-tests/specs/api/order.test.js create mode 100644 tests/e2e/specs/rest-api/order.js diff --git a/tests/e2e/api/src/models/index.ts b/tests/e2e/api/src/models/index.ts index 13ce569f196..902fdec58e3 100644 --- a/tests/e2e/api/src/models/index.ts +++ b/tests/e2e/api/src/models/index.ts @@ -3,3 +3,4 @@ export * from './model'; export * from './settings'; export * from './shared-types'; export * from './coupons'; +export * from './orders'; diff --git a/tests/e2e/api/src/models/orders/index.ts b/tests/e2e/api/src/models/orders/index.ts index de526a0af64..d4df1e6ca90 100644 --- a/tests/e2e/api/src/models/orders/index.ts +++ b/tests/e2e/api/src/models/orders/index.ts @@ -1,2 +1,2 @@ -export * from './shared'; export * from './orders'; +export * from './shared'; diff --git a/tests/e2e/api/src/models/orders/orders.ts b/tests/e2e/api/src/models/orders/orders.ts index 04fd8a93282..d23c4ca7611 100644 --- a/tests/e2e/api/src/models/orders/orders.ts +++ b/tests/e2e/api/src/models/orders/orders.ts @@ -1,5 +1,5 @@ -//import { HTTPClient } from '../../http'; -//import { orderRESTRepository } from '../../repositories'; +import { HTTPClient } from '../../http'; +import { orderRESTRepository } from '../../repositories'; import { ModelRepositoryParams, CreatesModels, @@ -50,47 +50,47 @@ type OrderUpdateParams = OrderAddressUpdateParams export type OrderRepositoryParams = ModelRepositoryParams< Order, never, never, OrderUpdateParams >; /** - * An interface for creating coupons using the repository. + * An interface for creating orders using the repository. * - * @typedef CreatesCoupons - * @alias CreatesModels. + * @typedef CreatesOrders + * @alias CreatesModels. */ -export type CreatesCoupons = CreatesModels< OrderRepositoryParams >; +export type CreatesOrders = CreatesModels< OrderRepositoryParams >; /** - * An interface for reading coupons using the repository. + * An interface for reading orders using the repository. * - * @typedef ReadsCoupons - * @alias ReadsModels. + * @typedef ReadsOrders + * @alias ReadsModels. */ -export type ReadsCoupons = ReadsModels< OrderRepositoryParams >; +export type ReadsOrders = ReadsModels< OrderRepositoryParams >; /** - * An interface for updating coupons using the repository. + * An interface for updating orders using the repository. * - * @typedef UpdatesCoupons - * @alias UpdatesModels. + * @typedef UpdatesOrders + * @alias UpdatesModels. */ -export type UpdatesCoupons = UpdatesModels< OrderRepositoryParams >; +export type UpdatesOrders = UpdatesModels< OrderRepositoryParams >; /** - * An interface for listing coupons using the repository. + * An interface for listing orders using the repository. * - * @typedef ListsCoupons - * @alias ListsModels. + * @typedef ListsOrders + * @alias ListsModels. */ -export type ListsCoupons = ListsModels< OrderRepositoryParams >; +export type ListsOrders = ListsModels< OrderRepositoryParams >; /** - * An interface for deleting coupons using the repository. + * An interface for deleting orders using the repository. * - * @typedef DeletesCoupons - * @alias DeletesModels. + * @typedef DeletesOrders + * @alias DeletesModels. */ -export type DeletesCoupons = DeletesModels< OrderRepositoryParams >; +export type DeletesOrders = DeletesModels< OrderRepositoryParams >; /** - * A coupon object. + * An order object. */ export class Order extends OrderItemMeta { /** @@ -289,6 +289,13 @@ export class Order extends OrderItemMeta { */ public readonly currencySymbol: string = ''; + /** + * The order's paid state. + * + * @type {boolean} + */ + public readonly setPaid: boolean = false; + /** * The order's line items. * @@ -342,7 +349,7 @@ export class Order extends OrderItemMeta { }; /** - * Creates a new coupon instance with the given properties + * Creates a new order instance with the given properties * * @param {Object} properties The properties to set in the object. */ @@ -350,15 +357,13 @@ export class Order extends OrderItemMeta { super(); Object.assign( this, properties ); } - /* + /** * Returns the repository for interacting with this type of model. * * @param {HTTPClient} httpClient The client for communicating via HTTP. */ - /* public static restRepository( httpClient: HTTPClient ): ReturnType< typeof orderRESTRepository > { return orderRESTRepository( httpClient ); } - */ } diff --git a/tests/e2e/api/src/models/orders/shared/classes.ts b/tests/e2e/api/src/models/orders/shared/classes.ts index f26923edcd5..540c543d4ae 100644 --- a/tests/e2e/api/src/models/orders/shared/classes.ts +++ b/tests/e2e/api/src/models/orders/shared/classes.ts @@ -36,7 +36,7 @@ export class OrderItemTax extends Model { /** * An order address. */ -export class OrderAddress { +export class OrderAddress extends Model { /** * The first name of the person in the address. * @@ -131,7 +131,7 @@ export class OrderLineItem extends OrderItemMeta { * * @type {number} */ - public readonly ProductId: number = -1; + public readonly productId: number = -1; /** * The ID of the product variation. diff --git a/tests/e2e/api/src/repositories/rest/index.ts b/tests/e2e/api/src/repositories/rest/index.ts index 15f18f10ee0..7ae5c9a38a2 100644 --- a/tests/e2e/api/src/repositories/rest/index.ts +++ b/tests/e2e/api/src/repositories/rest/index.ts @@ -1,3 +1,4 @@ -export * from './products'; -export * from './settings'; export * from './coupons'; +export * from './products'; +export * from './orders'; +export * from './settings'; diff --git a/tests/e2e/api/src/repositories/rest/orders/index.ts b/tests/e2e/api/src/repositories/rest/orders/index.ts index e69de29bb2d..fa4dd50d134 100644 --- a/tests/e2e/api/src/repositories/rest/orders/index.ts +++ b/tests/e2e/api/src/repositories/rest/orders/index.ts @@ -0,0 +1,3 @@ +import orderRESTRepository from './order'; + +export { orderRESTRepository }; diff --git a/tests/e2e/api/src/repositories/rest/orders/order.ts b/tests/e2e/api/src/repositories/rest/orders/order.ts index e69de29bb2d..76e29525982 100644 --- a/tests/e2e/api/src/repositories/rest/orders/order.ts +++ b/tests/e2e/api/src/repositories/rest/orders/order.ts @@ -0,0 +1,47 @@ +import { HTTPClient } from '../../../http'; +import { + ModelRepository, +} from '../../../framework'; +import { + ModelID, + Order, + OrderRepositoryParams, + ListsOrders, + ReadsOrders, + UpdatesOrders, + CreatesOrders, + DeletesOrders, +} from '../../../models'; + +import { + restList, + restCreate, + restRead, + restUpdate, + restDelete, +} from '../shared'; + +import { createOrderTransformer } from './transformer'; +/** + * + * @param {HTTPClient} httpClient The HTTP client for the REST requests to be made using. + */ +export default function orderRESTRepository( httpClient: HTTPClient ): CreatesOrders +& ListsOrders +& ReadsOrders +& UpdatesOrders +& DeletesOrders { + const buildURL = ( id: ModelID ) => '/wc/v3/orders/' + id; + // Using `?force=true` permanently deletes the order + const buildDeleteUrl = ( id: ModelID ) => `/wc/v3/orders/${ id }?force=true`; + + const transformer = createOrderTransformer(); + + return new ModelRepository( + restList< OrderRepositoryParams >( () => '/wc/v3/orders', Order, httpClient, transformer ), + restCreate< OrderRepositoryParams >( () => '/wc/v3/orders', Order, httpClient, transformer ), + restRead< OrderRepositoryParams >( buildURL, Order, httpClient, transformer ), + restUpdate< OrderRepositoryParams >( buildURL, Order, httpClient, transformer ), + restDelete< OrderRepositoryParams >( buildDeleteUrl, httpClient ), + ); +} diff --git a/tests/e2e/api/src/repositories/rest/orders/transformer.ts b/tests/e2e/api/src/repositories/rest/orders/transformer.ts index 41452a2ce26..5cd3c0e2b6f 100644 --- a/tests/e2e/api/src/repositories/rest/orders/transformer.ts +++ b/tests/e2e/api/src/repositories/rest/orders/transformer.ts @@ -1,24 +1,277 @@ import { - AddPropertyTransformation, - CustomTransformation, IgnorePropertyTransformation, KeyChangeTransformation, - ModelTransformation, ModelTransformer, ModelTransformerTransformation, PropertyType, PropertyTypeTransformation, - TransformationOrder, } from '../../../framework'; import { + Order, OrderAddress, OrderCouponLine, OrderFeeLine, - OrderItemTax, OrderLineItem, OrderRefundLine, OrderShippingLine, - OrderStatus, OrderTaxRate, } from '../../../models'; -import { createMetaDataTransformer } from '../shared'; + +/** + * Creates a transformer for an order object. + * + * @return {ModelTransformer} The created transformer. + */ +export function createOrderTransformer(): ModelTransformer< Order > { + return new ModelTransformer( + [ + new IgnorePropertyTransformation( [ 'date_created', 'date_modified' ] ), + new ModelTransformerTransformation( 'billing', OrderAddress, createOrderAddressTransformer() ), + new ModelTransformerTransformation( 'tax_lines', OrderTaxRate, createOrderTaxRateTransformer() ), + new ModelTransformerTransformation( 'refunds', OrderRefundLine, createOrderRefundLineTransformer() ), + new ModelTransformerTransformation( 'coupon_lines', OrderCouponLine, createOrdeCouponLineTransformer() ), + new ModelTransformerTransformation( 'fee_lines', OrderFeeLine, createOrderFeeLineTransformer() ), + new ModelTransformerTransformation( 'line_items', OrderLineItem, createOrderLineItemTransformer() ), + new ModelTransformerTransformation( 'shipping_lines', OrderShippingLine, createOrderShippingItemTransformer() ), + + new PropertyTypeTransformation( + { + status: PropertyType.String, + currency: PropertyType.String, + discountTotal: PropertyType.String, + discountTax: PropertyType.String, + shippingTotal: PropertyType.String, + shippingTax: PropertyType.String, + cartTax: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + pricesIncludeTax: PropertyType.Boolean, + customerId: PropertyType.Integer, + customerNote: PropertyType.String, + paymentMethod: PropertyType.String, + transactionId: PropertyType.String, + setPaid: PropertyType.Boolean, + }, + ), + new KeyChangeTransformation< Order >( + { + discountTotal: 'discount_total', + discountTax: 'discount_tax', + shippingTotal: 'shipping_total', + shippingTax: 'shipping_tax', + cartTax: 'cart_tax', + totalTax: 'total_tax', + pricesIncludeTax: 'prices_include_tax', + customerId: 'customer_id', + customerNote: 'customer_note', + paymentMethod: 'payment_method', + transactionId: 'transaction_id', + setPaid: 'set_paid', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order address object. + * + * @return {ModelTransformer} The created transformer. + */ +export function createOrderAddressTransformer(): ModelTransformer< OrderAddress > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + firstName: PropertyType.String, + lastName: PropertyType.String, + company: PropertyType.String, + address1: PropertyType.String, + address2: PropertyType.String, + city: PropertyType.String, + state: PropertyType.String, + postCode: PropertyType.String, + country: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderAddress >( + { + firstName: 'first_name', + lastName: 'last_name', + address1: 'address_1', + address2: 'address_2', + postCode: 'postcode', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order tax rate object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderTaxRateTransformer(): ModelTransformer< OrderTaxRate > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + rateCode: PropertyType.String, + rateId: PropertyType.Integer, + label: PropertyType.String, + compoundRate: PropertyType.Boolean, + taxTotal: PropertyType.String, + shippingTaxTotal: PropertyType.String, + ratePercent: PropertyType.Integer, + }, + ), + new KeyChangeTransformation< OrderTaxRate >( + { + rateCode: 'rate_code', + rateId: 'rate_id', + compoundRate: 'compound', + taxTotal: 'tax_total', + shippingTaxTotal: 'shipping_tax_total', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order refund line object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderRefundLineTransformer(): ModelTransformer< OrderRefundLine > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + reason: PropertyType.String, + total: PropertyType.String, + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order coupon line object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrdeCouponLineTransformer(): ModelTransformer< OrderCouponLine > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + code: PropertyType.String, + discount: PropertyType.Integer, + discountTax: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderCouponLine >( + { + discountTax: 'discount_tax', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order fee line object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderFeeLineTransformer(): ModelTransformer< OrderFeeLine > { + return new ModelTransformer( + [ + new ModelTransformerTransformation( 'taxes', OrderTaxRate, createOrderTaxRateTransformer() ), + new PropertyTypeTransformation( + { + name: PropertyType.String, + taxClass: PropertyType.String, + taxStatus: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderFeeLine >( + { + taxClass: 'tax_class', + taxStatus: 'tax_status', + totalTax: 'total_tax', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order line item object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderLineItemTransformer(): ModelTransformer< OrderLineItem > { + return new ModelTransformer( + [ + new ModelTransformerTransformation( 'taxes', OrderTaxRate, createOrderTaxRateTransformer() ), + new PropertyTypeTransformation( + { + name: PropertyType.String, + productId: PropertyType.Integer, + variationId: PropertyType.Integer, + quantity: PropertyType.Integer, + taxClass: PropertyType.String, + subtotal: PropertyType.String, + subtotalTax: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + sku: PropertyType.String, + price: PropertyType.Integer, + parentName: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderLineItem >( + { + productId: 'product_id', + variationId: 'variation_id', + taxClass: 'tax_class', + subtotalTax: 'subtotal_tax', + totalTax: 'total_tax', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order shipping line item object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderShippingItemTransformer(): ModelTransformer< OrderShippingLine > { + return new ModelTransformer( + [ + new ModelTransformerTransformation( 'taxes', OrderTaxRate, createOrderTaxRateTransformer() ), + new PropertyTypeTransformation( + { + methodTitle: PropertyType.String, + methodId: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderShippingLine >( + { + methodTitle: 'method_title', + methodId: 'method_id', + totalTax: 'total_tax', + }, + ), + ], + ); +} diff --git a/tests/e2e/config/default.json b/tests/e2e/config/default.json index 4d6b397aac2..adb8538915e 100644 --- a/tests/e2e/config/default.json +++ b/tests/e2e/config/default.json @@ -180,6 +180,17 @@ } } }, + "orders": { + "basicPaidOrder": { + "paymentMethod": "cod", + "status": "processing", + "billing": { + "firstName": "John", + "lastName": "Doe", + "email": "john.doe@example.com" + } + } + }, "onboardingwizard": { "industry": "Test industry", "numberofproducts": "1 - 10", diff --git a/tests/e2e/core-tests/specs/api/order.test.js b/tests/e2e/core-tests/specs/api/order.test.js new file mode 100644 index 00000000000..cdfc0b7a5c1 --- /dev/null +++ b/tests/e2e/core-tests/specs/api/order.test.js @@ -0,0 +1,82 @@ +/* eslint-disable jest/no-export, jest/no-disabled-tests */ +/** + * Internal dependencies + */ + const { HTTPClientFactory, Order } = require( '@woocommerce/api' ); + + /** + * External dependencies + */ + const config = require( 'config' ); + const { + it, + describe, + beforeAll, + } = require( '@jest/globals' ); + + /** + * Creates an order and tests interactions with it via the API. + */ +const runOrderApiTest = () => { + describe('REST API > Order', () => { + let client; + let order; + let repository; + + beforeAll(async () => { + order = config.get( 'orders.basicPaidOrder' ); + const admin = config.get( 'users.admin' ); + const url = config.get( 'url' ); + + client = HTTPClientFactory.build( url ) + .withBasicAuth( admin.username, admin.password ) + .withIndexPermalinks() + .create(); + } ); + + it('can create an order', async () => { + repository = Order.restRepository( client ); + + // Check properties of the order in the create order response. + order = await repository.create( order ); + expect( order ).toEqual( expect.objectContaining( order ) ); + }); + + it('can retrieve an order', async () => { + const orderProperties = { + id: order.id, + payment_method: order.paymentMethod, + status: order.status, + }; + + // Read order directly from API to compare. + const response = await client.get( `/wc/v3/orders/${order.id}` ); + expect( response.statusCode ).toBe( 200 ); + expect( response.data ).toEqual( expect.objectContaining( orderProperties ) ); + }); + + it('can update an order', async () => { + const updatedOrderProperties = { + payment_method: 'bacs', + status: 'completed', + }; + + await repository.update( order.id, updatedOrderProperties ); + + // Check the order response for the updated values. + const response = await client.get( `/wc/v3/orders/${order.id}` ); + expect( response.statusCode ).toBe( 200 ); + expect( response.data ).toEqual( expect.objectContaining( updatedOrderProperties ) ); + }); + + it('can delete an order', async () => { + // Delete the order + const status = await repository.delete( order.id ); + + // If the delete is successful, the response comes back truthy + expect( status ).toBeTruthy(); + }); + }); +}; + +module.exports = runOrderApiTest; diff --git a/tests/e2e/core-tests/specs/index.js b/tests/e2e/core-tests/specs/index.js index a0eca5a730f..12ecebb3c24 100644 --- a/tests/e2e/core-tests/specs/index.js +++ b/tests/e2e/core-tests/specs/index.js @@ -51,6 +51,7 @@ const runExternalProductAPITest = require( './api/external-product.test' ); const runCouponApiTest = require( './api/coupon.test' ); const runGroupedProductAPITest = require( './api/grouped-product.test' ); const runVariableProductAPITest = require( './api/variable-product.test' ); +const runOrderApiTest = require( './api/order.test' ); const runSetupOnboardingTests = () => { runActivationTest(); @@ -104,6 +105,7 @@ const runApiTests = () => { runGroupedProductAPITest(); runVariableProductAPITest(); runCouponApiTest(); + runOrderApiTest(); } module.exports = { @@ -133,6 +135,7 @@ module.exports = { runUpdateGeneralSettingsTest, runProductSettingsTest, runTaxSettingsTest, + runOrderApiTest, runOrderStatusFiltersTest, runOrderRefundTest, runOrderApplyCouponTest, diff --git a/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js b/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js index ad18a8de6d1..3b69ba28beb 100644 --- a/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js +++ b/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js @@ -11,7 +11,6 @@ const { } = require( '@woocommerce/e2e-utils' ); const config = require( 'config' ); -const simpleProductName = config.get( 'products.simple.name' ); const customerEmail = config.get( 'addresses.customer.billing.email' ); const adminEmail = 'admin@woocommercecoree2etestsuite.com'; const storeName = 'WooCommerce Core E2E Test Suite'; diff --git a/tests/e2e/specs/rest-api/order.js b/tests/e2e/specs/rest-api/order.js new file mode 100644 index 00000000000..d73a8be5f28 --- /dev/null +++ b/tests/e2e/specs/rest-api/order.js @@ -0,0 +1,6 @@ +/* + * Internal dependencies + */ +const { runOrderApiTest } = require( '@woocommerce/e2e-core-tests' ); + +runOrderApiTest(); From f7a4aba2cb44dc490b72e98fd174b8feb84f8bd1 Mon Sep 17 00:00:00 2001 From: Marco Almeida Date: Wed, 5 May 2021 18:21:54 +0100 Subject: [PATCH 13/42] Check for needs_payment() instead of has_status( 'pending' ) If an order needs payment, it should include the payment link, no matter the status. Fixes #29832 --- templates/emails/customer-invoice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/emails/customer-invoice.php b/templates/emails/customer-invoice.php index e0564448390..139512a5b22 100644 --- a/templates/emails/customer-invoice.php +++ b/templates/emails/customer-invoice.php @@ -29,7 +29,7 @@ do_action( 'woocommerce_email_header', $email_heading, $email ); ?>

get_billing_first_name() ) ); ?>

-has_status( 'pending' ) ) { ?> +needs_payment() ) { ?>

Date: Thu, 6 May 2021 12:55:30 +0100 Subject: [PATCH 14/42] Added `output_ad_block` method to `WC_Admin_Addons` and CSS rules to render a WooCommerce Payments ad banner at the top of the "Featured" section of the WC Core addons page, `wp-admin/admin.php?page=wc-addons§ion=_featured`. This is to fulfil the requirements of WooCommerce.com issue https://github.com/Automattic/woocommerce.com/issues/9860. We output the block if - The user has permissions to install plugins. - Their location is in one of the countries identified in a `geowhitelist`. - WooCommerce Payments is not already active. --- assets/css/admin.scss | 141 +++++++++++++++------ includes/admin/class-wc-admin-addons.php | 152 ++++++++++++++++------- 2 files changed, 212 insertions(+), 81 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 3dca45bdf8c..3cfc1495fdd 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -1,4 +1,3 @@ - /** * admin.scss * General WooCommerce admin styles. Settings, product data tabs, reports, etc. @@ -102,6 +101,43 @@ height: 62px; } + .addons-ad-block { + display: flex; + padding: 20px; + + .addons-img { + height: auto; + width: 200px; + } + } + + .addons-ad-block-content { + display: flex; + flex-direction: column; + margin-left: 24px; + } + + .addons-ad-block-description { + margin-bottom: 20px; + } + + .addons-ad-block-title { + margin: 0 0 16px; + padding: 0; + } + + .addons-ad-block-buttons { + margin-top: auto; + + .addons-button { + margin-right: 8px; + + &:last-child { + margin-right: 0; + } + } + } + .addons-banner-block p { margin: 0 0 20px; } @@ -364,6 +400,12 @@ color: #fff; } + .addons-button-expandable { + display: inline-block; + padding: 0 16px; + width: auto !important; + } + .addons-button-solid:hover { color: #fff; opacity: 0.8; @@ -451,9 +493,8 @@ flex: 1; overflow: hidden; background: #f5f5f5; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.2), - inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), + inset 0 -1px 0 rgba(0, 0, 0, 0.1); a { text-decoration: none; @@ -645,7 +686,7 @@ mark.amount { &::after { - @include icon_dashicons( "\f223" ); + @include icon_dashicons("\f223"); cursor: help; } } @@ -830,7 +871,7 @@ table.wc_status_table--tools { } // Adjust log table columns only when table is not collapsed - @media screen and ( min-width: 783px ) { + @media screen and (min-width: 783px) { .column-timestamp { width: 18%; @@ -1021,7 +1062,7 @@ ul.wc_coupon_list { &::before { - @include icon_dashicons( "\f158" ); + @include icon_dashicons("\f158"); } &:hover::before { @@ -1065,7 +1106,7 @@ ul.wc_coupon_list_block { &::after { - @include icon_dashicons( "\f345" ); + @include icon_dashicons("\f345"); line-height: 28px; } } @@ -1589,7 +1630,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f128" ); + @include icon_dashicons("\f128"); width: 38px; line-height: 38px; display: block; @@ -1837,7 +1878,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e007" ); + @include icon("\e007"); color: #ccc; } } @@ -1852,7 +1893,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e014" ); + @include icon("\e014"); color: #ccc; } } @@ -1869,7 +1910,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e01a" ); + @include icon("\e01a"); color: #ccc; } } @@ -1898,7 +1939,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f153" ); + @include icon_dashicons("\f153"); color: #999; } @@ -1920,7 +1961,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f171" ); + @include icon_dashicons("\f171"); position: relative; top: auto; left: auto; @@ -1976,7 +2017,7 @@ ul.wc_coupon_list_block { .edit-order-item::before { - @include icon_dashicons( "\f464" ); + @include icon_dashicons("\f464"); position: relative; } @@ -1985,7 +2026,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f158" ); + @include icon_dashicons("\f158"); position: relative; } @@ -2353,7 +2394,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e010" ); + @include icon("\e010"); line-height: 16px; font-size: 14px; vertical-align: middle; @@ -2642,6 +2683,29 @@ ul.wc_coupon_list_block { float: right; } } + + .wc_addons_wrap { + .addons-ad-block { + flex-direction: column; + padding: 24px; + + .addons-img { + height: auto; + width: 100%; + max-width: 240px; + margin: 0 auto 20px; + } + } + + .addons-ad-block-content { + display: block; + margin-left: 0; + } + + .addons-ad-block-title { + margin-top: 4px; + } + } } .column-customer_message .note-on { @@ -2652,7 +2716,7 @@ ul.wc_coupon_list_block { &::after { - @include icon( "\e026" ); + @include icon("\e026"); line-height: 16px; } } @@ -2665,7 +2729,7 @@ ul.wc_coupon_list_block { &::after { - @include icon( "\e027" ); + @include icon("\e027"); line-height: 16px; } } @@ -2902,7 +2966,7 @@ table.wp-list-table { &::before { - @include icon_dashicons( "\f128" ); + @include icon_dashicons("\f128"); } } @@ -3867,19 +3931,19 @@ img.help_tip { .status-manual::before { - @include icon( "\e008" ); + @include icon("\e008"); color: #999; } .status-enabled::before { - @include icon( "\e015" ); + @include icon("\e015"); color: $woocommerce; } .status-disabled::before { - @include icon( "\e013" ); + @include icon("\e013"); color: #ccc; } @@ -4298,7 +4362,7 @@ img.help_tip { &::after { - @include icon_dashicons( "\f161" ); + @include icon_dashicons("\f161"); font-size: 2.618em; line-height: 72px; color: #ddd; @@ -4340,7 +4404,7 @@ img.help_tip { &::before { - @include icon_dashicons( "\f153" ); + @include icon_dashicons("\f153"); color: #999; background: #fff; border-radius: 50%; @@ -4527,7 +4591,7 @@ img.help_tip { &::before { - @include iconbeforedashicons( "\f107" ); + @include iconbeforedashicons("\f107"); } } @@ -4611,7 +4675,7 @@ img.help_tip { .add.button::before { - @include iconbefore( "\e007" ); + @include iconbefore("\e007"); } } @@ -4727,7 +4791,7 @@ img.help_tip { &::before { - @include icon_dashicons( "\f153" ); + @include icon_dashicons("\f153"); color: #999; } @@ -5642,7 +5706,7 @@ img.ui-datepicker-trigger { &::before { - @include iconbeforedashicons( "\f346" ); + @include iconbeforedashicons("\f346"); margin-right: 4px; } } @@ -5769,7 +5833,7 @@ img.ui-datepicker-trigger { &::after { - @include iconafter( "\e035" ); + @include iconafter("\e035"); float: right; font-size: 0.9em; line-height: 1.618; @@ -5902,9 +5966,8 @@ img.ui-datepicker-trigger { } &:hover { - box-shadow: - inset 0 -1px 0 0 #dfdfdf, - inset 300px 0 0 rgba(156, 93, 144, 0.1); + box-shadow: inset 0 -1px 0 0 #dfdfdf, + inset 300px 0 0 rgba(156, 93, 144, 0.1); border-right: 5px solid #9c5d90 !important; padding-left: 1.5em; color: #9c5d90; @@ -6104,27 +6167,27 @@ table.bar_chart { .post-type-shop_order .woocommerce-BlankState-message::before { - @include icon( "\e01d" ); + @include icon("\e01d"); } .post-type-shop_coupon .woocommerce-BlankState-message::before { - @include icon( "\e600" ); + @include icon("\e600"); } .post-type-product .woocommerce-BlankState-message::before { - @include icon( "\e006" ); + @include icon("\e006"); } .woocommerce-BlankState--api .woocommerce-BlankState-message::before { - @include icon( "\e01c" ); + @include icon("\e01c"); } .woocommerce-BlankState--webhooks .woocommerce-BlankState-message::before { - @include icon( "\e01b" ); + @include icon("\e01b"); } .woocommerce-BlankState { @@ -7298,7 +7361,7 @@ table.bar_chart { &::before { - @include icon( "\e015" ); + @include icon("\e015"); color: #a16696; position: static; font-size: 100px; diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index ed3a0461368..7c80211290e 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -50,6 +50,7 @@ class WC_Admin_Addons { if ( is_object( $featured ) ) { self::output_featured_sections( $featured->sections ); + return $featured; } } @@ -57,9 +58,9 @@ class WC_Admin_Addons { /** * Build url parameter string * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return string url parameter string */ @@ -77,14 +78,14 @@ class WC_Admin_Addons { /** * Call API to get extensions * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return array of extensions */ public static function get_extension_data( $category, $term, $country ) { - $parameters = self::build_parameter_string( $category, $term, $country ); + $parameters = self::build_parameter_string( $category, $term, $country ); $headers = array(); $auth = WC_Helper_Options::get( 'auth' ); @@ -101,6 +102,7 @@ class WC_Admin_Addons { if ( ! is_wp_error( $raw_extensions ) ) { $addons = json_decode( wp_remote_retrieve_body( $raw_extensions ) )->products; } + return $addons; } @@ -122,13 +124,14 @@ class WC_Admin_Addons { } } } + return apply_filters( 'woocommerce_addons_sections', $addon_sections ); } /** * Get section for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return object|bool */ @@ -137,13 +140,14 @@ class WC_Admin_Addons { if ( isset( $sections[ $section_id ] ) ) { return $sections[ $section_id ]; } + return false; } /** * Get section content for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return array */ @@ -226,12 +230,12 @@ class WC_Admin_Addons {

title ); ?>

description ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?> @@ -288,12 +292,12 @@ class WC_Admin_Addons {

title ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?>

description ); ?>

@@ -320,11 +324,11 @@ class WC_Admin_Addons {
buttons as $button ) : ?> href, - $button->text, - 'addons-button-solid' - ); + self::output_button( + $button->href, + $button->text, + 'addons-button-solid' + ); ?>
@@ -352,11 +356,11 @@ class WC_Admin_Addons { href, - $item->button, - 'addons-button-outline-white' - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-outline-white' + ); ?> @@ -461,11 +465,11 @@ class WC_Admin_Addons { @@ -523,17 +527,75 @@ class WC_Admin_Addons {

geowhitelist ) ) { + $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); + } + + if ( ! self::show_extension( $section_object ) ) { + return; + } + + ?> +
+ <?php echo esc_attr( $section['image_alt'] ); ?> +
+

+
+ +
+
+ +
+
+
+ site_url(), 'wccom-back' => rawurlencode( $back_admin_path ), @@ -591,7 +657,7 @@ class WC_Admin_Addons { * Adds various url parameters to a url to support a streamlined * flow for obtaining and setting up WooCommerce extensons. * - * @param string $url Destination URL. + * @param string $url Destination URL. */ public static function add_in_app_purchase_url_params( $url ) { return add_query_arg( @@ -632,6 +698,7 @@ class WC_Admin_Addons { if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) { do_action( 'woocommerce_helper_output' ); + return; } @@ -718,6 +785,7 @@ class WC_Admin_Addons { * Should an extension be shown on the featured page. * * @param object $item Item data. + * * @return boolean */ public static function show_extension( $item ) { From f1a69cb4afcd1bad6f1f224f028712603b3df528 Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 15:16:49 +0100 Subject: [PATCH 15/42] Added comment to new `output_ad_block` method. Removed differences introduced by PhpStorm autoformat. --- assets/css/admin.scss | 150 ++++++++++++----------- includes/admin/class-wc-admin-addons.php | 96 +++++++-------- 2 files changed, 124 insertions(+), 122 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 3cfc1495fdd..cc06dd14e7e 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -1,3 +1,4 @@ + /** * admin.scss * General WooCommerce admin styles. Settings, product data tabs, reports, etc. @@ -101,43 +102,6 @@ height: 62px; } - .addons-ad-block { - display: flex; - padding: 20px; - - .addons-img { - height: auto; - width: 200px; - } - } - - .addons-ad-block-content { - display: flex; - flex-direction: column; - margin-left: 24px; - } - - .addons-ad-block-description { - margin-bottom: 20px; - } - - .addons-ad-block-title { - margin: 0 0 16px; - padding: 0; - } - - .addons-ad-block-buttons { - margin-top: auto; - - .addons-button { - margin-right: 8px; - - &:last-child { - margin-right: 0; - } - } - } - .addons-banner-block p { margin: 0 0 20px; } @@ -197,6 +161,43 @@ } } + .addons-ad-block { + display: flex; + padding: 20px; + + .addons-img { + height: auto; + width: 200px; + } + } + + .addons-ad-block-content { + display: flex; + flex-direction: column; + margin-left: 24px; + } + + .addons-ad-block-description { + margin-bottom: 20px; + } + + .addons-ad-block-title { + margin: 0 0 16px; + padding: 0; + } + + .addons-ad-block-buttons { + margin-top: auto; + + .addons-button { + margin-right: 8px; + + &:last-child { + margin-right: 0; + } + } + } + .addons-shipping-methods .addons-wcs-banner-block { margin-left: 0; margin-right: 0; @@ -493,8 +494,9 @@ flex: 1; overflow: hidden; background: #f5f5f5; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), - inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.2), + inset 0 -1px 0 rgba(0, 0, 0, 0.1); a { text-decoration: none; @@ -686,7 +688,7 @@ mark.amount { &::after { - @include icon_dashicons("\f223"); + @include icon_dashicons( "\f223" ); cursor: help; } } @@ -871,7 +873,7 @@ table.wc_status_table--tools { } // Adjust log table columns only when table is not collapsed - @media screen and (min-width: 783px) { + @media screen and ( min-width: 783px ) { .column-timestamp { width: 18%; @@ -1062,7 +1064,7 @@ ul.wc_coupon_list { &::before { - @include icon_dashicons("\f158"); + @include icon_dashicons( "\f158" ); } &:hover::before { @@ -1106,7 +1108,7 @@ ul.wc_coupon_list_block { &::after { - @include icon_dashicons("\f345"); + @include icon_dashicons( "\f345" ); line-height: 28px; } } @@ -1630,7 +1632,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f128"); + @include icon_dashicons( "\f128" ); width: 38px; line-height: 38px; display: block; @@ -1878,7 +1880,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e007"); + @include icon( "\e007" ); color: #ccc; } } @@ -1893,7 +1895,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e014"); + @include icon( "\e014" ); color: #ccc; } } @@ -1910,7 +1912,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e01a"); + @include icon( "\e01a" ); color: #ccc; } } @@ -1939,7 +1941,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f153"); + @include icon_dashicons( "\f153" ); color: #999; } @@ -1961,7 +1963,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f171"); + @include icon_dashicons( "\f171" ); position: relative; top: auto; left: auto; @@ -2017,7 +2019,7 @@ ul.wc_coupon_list_block { .edit-order-item::before { - @include icon_dashicons("\f464"); + @include icon_dashicons( "\f464" ); position: relative; } @@ -2026,7 +2028,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f158"); + @include icon_dashicons( "\f158" ); position: relative; } @@ -2394,7 +2396,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e010"); + @include icon( "\e010" ); line-height: 16px; font-size: 14px; vertical-align: middle; @@ -2685,6 +2687,7 @@ ul.wc_coupon_list_block { } .wc_addons_wrap { + .addons-ad-block { flex-direction: column; padding: 24px; @@ -2716,7 +2719,7 @@ ul.wc_coupon_list_block { &::after { - @include icon("\e026"); + @include icon( "\e026" ); line-height: 16px; } } @@ -2729,7 +2732,7 @@ ul.wc_coupon_list_block { &::after { - @include icon("\e027"); + @include icon( "\e027" ); line-height: 16px; } } @@ -2966,7 +2969,7 @@ table.wp-list-table { &::before { - @include icon_dashicons("\f128"); + @include icon_dashicons( "\f128" ); } } @@ -3931,19 +3934,19 @@ img.help_tip { .status-manual::before { - @include icon("\e008"); + @include icon( "\e008" ); color: #999; } .status-enabled::before { - @include icon("\e015"); + @include icon( "\e015" ); color: $woocommerce; } .status-disabled::before { - @include icon("\e013"); + @include icon( "\e013" ); color: #ccc; } @@ -4362,7 +4365,7 @@ img.help_tip { &::after { - @include icon_dashicons("\f161"); + @include icon_dashicons( "\f161" ); font-size: 2.618em; line-height: 72px; color: #ddd; @@ -4404,7 +4407,7 @@ img.help_tip { &::before { - @include icon_dashicons("\f153"); + @include icon_dashicons( "\f153" ); color: #999; background: #fff; border-radius: 50%; @@ -4591,7 +4594,7 @@ img.help_tip { &::before { - @include iconbeforedashicons("\f107"); + @include iconbeforedashicons( "\f107" ); } } @@ -4675,7 +4678,7 @@ img.help_tip { .add.button::before { - @include iconbefore("\e007"); + @include iconbefore( "\e007" ); } } @@ -4791,7 +4794,7 @@ img.help_tip { &::before { - @include icon_dashicons("\f153"); + @include icon_dashicons( "\f153" ); color: #999; } @@ -5706,7 +5709,7 @@ img.ui-datepicker-trigger { &::before { - @include iconbeforedashicons("\f346"); + @include iconbeforedashicons( "\f346" ); margin-right: 4px; } } @@ -5833,7 +5836,7 @@ img.ui-datepicker-trigger { &::after { - @include iconafter("\e035"); + @include iconafter( "\e035" ); float: right; font-size: 0.9em; line-height: 1.618; @@ -5966,8 +5969,9 @@ img.ui-datepicker-trigger { } &:hover { - box-shadow: inset 0 -1px 0 0 #dfdfdf, - inset 300px 0 0 rgba(156, 93, 144, 0.1); + box-shadow: + inset 0 -1px 0 0 #dfdfdf, + inset 300px 0 0 rgba(156, 93, 144, 0.1); border-right: 5px solid #9c5d90 !important; padding-left: 1.5em; color: #9c5d90; @@ -6167,27 +6171,27 @@ table.bar_chart { .post-type-shop_order .woocommerce-BlankState-message::before { - @include icon("\e01d"); + @include icon( "\e01d" ); } .post-type-shop_coupon .woocommerce-BlankState-message::before { - @include icon("\e600"); + @include icon( "\e600" ); } .post-type-product .woocommerce-BlankState-message::before { - @include icon("\e006"); + @include icon( "\e006" ); } .woocommerce-BlankState--api .woocommerce-BlankState-message::before { - @include icon("\e01c"); + @include icon( "\e01c" ); } .woocommerce-BlankState--webhooks .woocommerce-BlankState-message::before { - @include icon("\e01b"); + @include icon( "\e01b" ); } .woocommerce-BlankState { @@ -7361,7 +7365,7 @@ table.bar_chart { &::before { - @include icon("\e015"); + @include icon( "\e015" ); color: #a16696; position: static; font-size: 100px; diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index 7c80211290e..c9aa5a2cd71 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -50,7 +50,6 @@ class WC_Admin_Addons { if ( is_object( $featured ) ) { self::output_featured_sections( $featured->sections ); - return $featured; } } @@ -58,9 +57,9 @@ class WC_Admin_Addons { /** * Build url parameter string * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return string url parameter string */ @@ -78,14 +77,14 @@ class WC_Admin_Addons { /** * Call API to get extensions * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return array of extensions */ public static function get_extension_data( $category, $term, $country ) { - $parameters = self::build_parameter_string( $category, $term, $country ); + $parameters = self::build_parameter_string( $category, $term, $country ); $headers = array(); $auth = WC_Helper_Options::get( 'auth' ); @@ -102,7 +101,6 @@ class WC_Admin_Addons { if ( ! is_wp_error( $raw_extensions ) ) { $addons = json_decode( wp_remote_retrieve_body( $raw_extensions ) )->products; } - return $addons; } @@ -124,14 +122,13 @@ class WC_Admin_Addons { } } } - return apply_filters( 'woocommerce_addons_sections', $addon_sections ); } /** * Get section for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return object|bool */ @@ -140,14 +137,13 @@ class WC_Admin_Addons { if ( isset( $sections[ $section_id ] ) ) { return $sections[ $section_id ]; } - return false; } /** * Get section content for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return array */ @@ -230,12 +226,12 @@ class WC_Admin_Addons {

title ); ?>

description ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?> @@ -292,12 +288,12 @@ class WC_Admin_Addons {

title ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?>

description ); ?>

@@ -324,11 +320,11 @@ class WC_Admin_Addons {
buttons as $button ) : ?> href, - $button->text, - 'addons-button-solid' - ); + self::output_button( + $button->href, + $button->text, + 'addons-button-solid' + ); ?>
@@ -356,11 +352,11 @@ class WC_Admin_Addons { href, - $item->button, - 'addons-button-outline-white' - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-outline-white' + ); ?> @@ -465,11 +461,11 @@ class WC_Admin_Addons { @@ -527,17 +523,22 @@ class WC_Admin_Addons {

site_url(), 'wccom-back' => rawurlencode( $back_admin_path ), @@ -657,7 +657,7 @@ class WC_Admin_Addons { * Adds various url parameters to a url to support a streamlined * flow for obtaining and setting up WooCommerce extensons. * - * @param string $url Destination URL. + * @param string $url Destination URL. */ public static function add_in_app_purchase_url_params( $url ) { return add_query_arg( @@ -698,7 +698,6 @@ class WC_Admin_Addons { if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) { do_action( 'woocommerce_helper_output' ); - return; } @@ -785,7 +784,6 @@ class WC_Admin_Addons { * Should an extension be shown on the featured page. * * @param object $item Item data. - * * @return boolean */ public static function show_extension( $item ) { From 2b053d45860a1f6dba8fb3f51853c507dd5e1719 Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 15:22:53 +0100 Subject: [PATCH 16/42] Added docblock comment for `$section` param. --- includes/admin/class-wc-admin-addons.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index c9aa5a2cd71..a168498d4f9 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -537,7 +537,7 @@ class WC_Admin_Addons { /** * Handles the output of a full-width block. * - * @param $section + * array $section Section data for this block, which is a section itself. */ public static function output_ad_block( $section ) { if ( From 21b4801cc1b8186a2d92e424e1b7ed5959633cbc Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 15:40:02 +0100 Subject: [PATCH 17/42] Fixing doc comment for new method. --- includes/admin/class-wc-admin-addons.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index a168498d4f9..0cfb28c1c82 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -537,7 +537,7 @@ class WC_Admin_Addons { /** * Handles the output of a full-width block. * - * array $section Section data for this block, which is a section itself. + * @param array $section Section data. */ public static function output_ad_block( $section ) { if ( From aa913b59ed56cf65fc37490c1c280d67ae901c8d Mon Sep 17 00:00:00 2001 From: Khoi Nguyen Date: Thu, 6 May 2021 22:22:58 +0700 Subject: [PATCH 18/42] Set loop prop to widget products to set condition on single product page --- includes/widgets/class-wc-widget-products.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/widgets/class-wc-widget-products.php b/includes/widgets/class-wc-widget-products.php index be373488920..4d5b61240a7 100644 --- a/includes/widgets/class-wc-widget-products.php +++ b/includes/widgets/class-wc-widget-products.php @@ -186,6 +186,8 @@ class WC_Widget_Products extends WC_Widget { ob_start(); + wc_set_loop_prop( 'name', 'widget' ); + $products = $this->get_products( $args, $instance ); if ( $products && $products->have_posts() ) { $this->widget_start( $args, $instance ); From e4d3b157ffa443213be66e82e110e9a27e3bc6c2 Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 22:12:07 +0100 Subject: [PATCH 19/42] Changed block name and CSS classnames to the more generic "promotion block". --- assets/css/admin.scss | 16 ++++++++-------- includes/admin/class-wc-admin-addons.php | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index cc06dd14e7e..35bc0dc12e3 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -161,7 +161,7 @@ } } - .addons-ad-block { + .addons-promotion-block { display: flex; padding: 20px; @@ -171,22 +171,22 @@ } } - .addons-ad-block-content { + .addons-promotion-block-content { display: flex; flex-direction: column; margin-left: 24px; } - .addons-ad-block-description { + .addons-promotion-block-description { margin-bottom: 20px; } - .addons-ad-block-title { + .addons-promotion-block-title { margin: 0 0 16px; padding: 0; } - .addons-ad-block-buttons { + .addons-promotion-block-buttons { margin-top: auto; .addons-button { @@ -2688,7 +2688,7 @@ ul.wc_coupon_list_block { .wc_addons_wrap { - .addons-ad-block { + .addons-promotion-block { flex-direction: column; padding: 24px; @@ -2700,12 +2700,12 @@ ul.wc_coupon_list_block { } } - .addons-ad-block-content { + .addons-promotion-block-content { display: block; margin-left: 0; } - .addons-ad-block-title { + .addons-promotion-block-title { margin-top: 4px; } } diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index 0cfb28c1c82..e90ac2ad9a8 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -539,7 +539,7 @@ class WC_Admin_Addons { * * @param array $section Section data. */ - public static function output_ad_block( $section ) { + public static function output_promotion_block( $section ) { if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'activate_plugins' ) @@ -558,18 +558,18 @@ class WC_Admin_Addons { } ?> -
+
<?php echo esc_attr( $section['image_alt'] ); ?> -
-

-
+
+

+
-
+
Date: Tue, 11 May 2021 11:37:28 -0400 Subject: [PATCH 20/42] update blocks package to 5.1.0 --- composer.json | 2 +- composer.lock | 61 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 462458e7920..6346176de2a 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", "woocommerce/woocommerce-admin": "2.2.6", - "woocommerce/woocommerce-blocks": "4.9.1" + "woocommerce/woocommerce-blocks": "5.1.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4" diff --git a/composer.lock b/composer.lock index 3f506ced4f6..16af2df5a8d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a604678b268820c78736d599e1eb6726", + "content-hash": "3f82e5bd9e485ba6bcd94111391f6f11", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -51,6 +51,9 @@ "GPL-2.0-or-later" ], "description": "Creates a custom autoloader for a plugin or theme.", + "support": { + "source": "https://github.com/Automattic/jetpack-autoloader/tree/2.10.1" + }, "time": "2021-03-30T15:15:59+00:00" }, { @@ -82,6 +85,9 @@ "GPL-2.0-or-later" ], "description": "A wrapper for defining constants in a more testable way.", + "support": { + "source": "https://github.com/Automattic/jetpack-constants/tree/v1.5.1" + }, "time": "2020-10-28T19:00:31+00:00" }, { @@ -214,6 +220,10 @@ "zend", "zikula" ], + "support": { + "issues": "https://github.com/composer/installers/issues", + "source": "https://github.com/composer/installers/tree/v1.11.0" + }, "funding": [ { "url": "https://packagist.com", @@ -288,6 +298,10 @@ "geolocation", "maxmind" ], + "support": { + "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.6.0" + }, "time": "2019-12-19T22:59:03+00:00" }, { @@ -362,6 +376,10 @@ "email", "pre-processing" ], + "support": { + "issues": "https://github.com/MyIntervals/emogrifier/issues", + "source": "https://github.com/MyIntervals/emogrifier" + }, "time": "2019-12-26T19:37:31+00:00" }, { @@ -411,6 +429,10 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/master" + }, "time": "2017-02-14T16:28:37+00:00" }, { @@ -464,6 +486,9 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/master" + }, "time": "2017-05-01T15:01:29+00:00" }, { @@ -499,6 +524,10 @@ ], "description": "Action Scheduler for WordPress and WooCommerce", "homepage": "https://actionscheduler.org/", + "support": { + "issues": "https://github.com/woocommerce/action-scheduler/issues", + "source": "https://github.com/woocommerce/action-scheduler/tree/master" + }, "time": "2020-05-12T16:22:33+00:00" }, { @@ -507,7 +536,7 @@ "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "161e6afa01a3fb69533cfa2b245a71df7512ec3f" + "reference": "65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8" }, "dist": { "type": "zip", @@ -544,20 +573,24 @@ ], "description": "A modern, javascript-driven WooCommerce Admin experience.", "homepage": "https://github.com/woocommerce/woocommerce-admin", - "time": "2021-04-29T14:11:48+00:00" + "support": { + "issues": "https://github.com/woocommerce/woocommerce-admin/issues", + "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.2.6" + }, + "time": "2021-05-07T21:29:02+00:00" }, { "name": "woocommerce/woocommerce-blocks", - "version": "v4.9.1", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", - "reference": "62f32bfb45dfcb2ba3ca349a6ed0a8cf48ddefce" + "reference": "a4f168596f3832e161b26dec636b69293039ee51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/62f32bfb45dfcb2ba3ca349a6ed0a8cf48ddefce", - "reference": "62f32bfb45dfcb2ba3ca349a6ed0a8cf48ddefce", + "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/a4f168596f3832e161b26dec636b69293039ee51", + "reference": "a4f168596f3832e161b26dec636b69293039ee51", "shasum": "" }, "require": { @@ -565,7 +598,7 @@ "composer/installers": "^1.7.0" }, "require-dev": { - "phpunit/phpunit": "6.5.14", + "phpunit/phpunit": "7.5.20", "woocommerce/woocommerce-sniffs": "0.1.0" }, "type": "wordpress-plugin", @@ -591,7 +624,11 @@ "gutenberg", "woocommerce" ], - "time": "2021-04-13T16:11:16+00:00" + "support": { + "issues": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues", + "source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v5.1.0" + }, + "time": "2021-05-10T15:01:42+00:00" } ], "packages-dev": [ @@ -639,6 +676,10 @@ "isolation", "tool" ], + "support": { + "issues": "https://github.com/bamarni/composer-bin-plugin/issues", + "source": "https://github.com/bamarni/composer-bin-plugin/tree/master" + }, "time": "2020-05-03T08:27:20+00:00" } ], @@ -654,5 +695,5 @@ "platform-overrides": { "php": "7.0" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } From de331ad8935d01eafc910d84fc4464469cfd1dac Mon Sep 17 00:00:00 2001 From: And Finally Date: Wed, 12 May 2021 09:41:31 +0100 Subject: [PATCH 21/42] Addressing feedback. Removed `!important` from `.addons-button-expandable` rule. Renamed `geowhitelist` and `geoblacklist` to `geo_allow_list` and `geo_block_list`. --- assets/css/admin.scss | 2 +- includes/admin/class-wc-admin-addons.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 35bc0dc12e3..6ea357b8e2a 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -404,7 +404,7 @@ .addons-button-expandable { display: inline-block; padding: 0 16px; - width: auto !important; + width: auto; } .addons-button-solid:hover { diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index e90ac2ad9a8..fafe07d5ce7 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -549,8 +549,8 @@ class WC_Admin_Addons { $section_object = (object) $section; - if ( ! empty( $section_object->geowhitelist ) ) { - $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); + if ( ! empty( $section_object->geo_allow_list ) ) { + $section_object->geo_allow_list = explode( ',', $section_object->geo_allow_list ); } if ( ! self::show_extension( $section_object ) ) { @@ -788,11 +788,11 @@ class WC_Admin_Addons { */ public static function show_extension( $item ) { $location = WC()->countries->get_base_country(); - if ( isset( $item->geowhitelist ) && ! in_array( $location, $item->geowhitelist, true ) ) { + if ( isset( $item->geo_allow_list ) && ! in_array( $location, $item->geo_allow_list, true ) ) { return false; } - if ( isset( $item->geoblacklist ) && in_array( $location, $item->geoblacklist, true ) ) { + if ( isset( $item->geo_block_list ) && in_array( $location, $item->geo_block_list, true ) ) { return false; } From 6bb1ec73a4757cf38ddb1893a06515ccb6263b57 Mon Sep 17 00:00:00 2001 From: And Finally Date: Wed, 12 May 2021 17:48:37 +0100 Subject: [PATCH 22/42] Reverted renaming of `geowhitelist` and `geoblacklist`, in case they are still present in other endpoints. --- includes/admin/class-wc-admin-addons.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index fafe07d5ce7..e90ac2ad9a8 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -549,8 +549,8 @@ class WC_Admin_Addons { $section_object = (object) $section; - if ( ! empty( $section_object->geo_allow_list ) ) { - $section_object->geo_allow_list = explode( ',', $section_object->geo_allow_list ); + if ( ! empty( $section_object->geowhitelist ) ) { + $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); } if ( ! self::show_extension( $section_object ) ) { @@ -788,11 +788,11 @@ class WC_Admin_Addons { */ public static function show_extension( $item ) { $location = WC()->countries->get_base_country(); - if ( isset( $item->geo_allow_list ) && ! in_array( $location, $item->geo_allow_list, true ) ) { + if ( isset( $item->geowhitelist ) && ! in_array( $location, $item->geowhitelist, true ) ) { return false; } - if ( isset( $item->geo_block_list ) && in_array( $location, $item->geo_block_list, true ) ) { + if ( isset( $item->geoblacklist ) && in_array( $location, $item->geoblacklist, true ) ) { return false; } From 7202f19631e474d1adc93d83acc1499bab0b6b3d Mon Sep 17 00:00:00 2001 From: And Finally Date: Wed, 12 May 2021 17:54:20 +0100 Subject: [PATCH 23/42] Added support for `geoblacklist` in `output_promotion_block`. --- includes/admin/class-wc-admin-addons.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index e90ac2ad9a8..ff33de129e0 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -553,6 +553,10 @@ class WC_Admin_Addons { $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); } + if ( ! empty( $section_object->geoblacklist ) ) { + $section_object->geoblacklist = explode( ',', $section_object->geoblacklist ); + } + if ( ! self::show_extension( $section_object ) ) { return; } From 7806ea2b5d25c9ce02511d1db143aadea79ea54d Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 13 May 2021 09:25:14 -0300 Subject: [PATCH 24/42] update remove stale on comment (#29882) * remove the stale label when feedback is provided * remove labels in separate steps --- .github/workflows/update-feedback-labels.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-feedback-labels.yml b/.github/workflows/update-feedback-labels.yml index 2c311f0195a..bb0af46f64b 100644 --- a/.github/workflows/update-feedback-labels.yml +++ b/.github/workflows/update-feedback-labels.yml @@ -15,10 +15,13 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: 'has feedback' - - name: remove needs feedback, stale + - name: remove needs feedback uses: actions-ecosystem/action-remove-labels@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} - labels: | - 'needs feedback' - 'Stale' + labels: 'needs feedback' + - name: remove stale + uses: actions-ecosystem/action-remove-labels@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: Stale From 2a86d2b2ab572bc0d3caad4056ba5f81a33589ab Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 13 May 2021 16:06:28 -0300 Subject: [PATCH 25/42] update api package readme & changelog to prep for release --- tests/e2e/api/CHANGELOG.md | 9 ++++++++- tests/e2e/api/README.md | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/e2e/api/CHANGELOG.md b/tests/e2e/api/CHANGELOG.md index a2c57debaf4..605741512f5 100644 --- a/tests/e2e/api/CHANGELOG.md +++ b/tests/e2e/api/CHANGELOG.md @@ -1,5 +1,12 @@ # Unreleased +## Added + +- Support for orders. + +## Changed + +- `delete()` now deletes products and coupons instead of moving to `trash`. # 0.1.2 @@ -14,7 +21,7 @@ ## Breaking Changes -- The `HTTPClientFactory` API was changed to make it easier to configure instances with +- The `HTTPClientFactory` API was changed to make it easier to configure instances ## Added diff --git a/tests/e2e/api/README.md b/tests/e2e/api/README.md index 7eadd2d5de1..21398557049 100644 --- a/tests/e2e/api/README.md +++ b/tests/e2e/api/README.md @@ -6,7 +6,7 @@ features: - [x] TypeScript Definitions - [x] Axios API Client with support for OAuth & basic auth - [x] Repositories to simplify interaction with basic data types -- [ ] Service classes for common activities such as changing settings +- [x] Service classes for common activities such as changing settings ## Usage @@ -51,12 +51,20 @@ httpClient.get( '/wc/v3/products' ).then( ( response ) => { As a convenience utility we've created repositories for core data types that can simplify interacting with the API: +#### Parent/Base Repositories + - `SimpleProduct` - `ExternalProduct` - `GroupedProduct` - `VariableProduct` -- `ProductVariation` - `Coupon` +- `Order` +- `SettingsGroup` + +#### Child Repositories + +- `ProductVariation` +- `Setting` These repositories provide CRUD methods for ease-of-use: @@ -80,7 +88,7 @@ product.id; #### Repository Methods -The following methods are available on all repositories: +The following methods are available on all repositories if the corresponding method is available on the API endpoint: - `create( {...properties} )` - Create a single object of the model type - `delete( objectId )` - Delete a single object of the model type @@ -90,14 +98,14 @@ The following methods are available on all repositories: #### Child Repositories -`ProductVariation` is a child model repository. In child model repositories, each method requires the `parentId` as the first parameter: +In child model repositories, each method requires the `parentId` as the first parameter: ```javascript import { HTTPClientFactory, VariableProduct, ProductVariation } from '@woocommerce/api'; const httpClient = HTTPClientFactory.build( 'https://example.com' ) .withBasicAuth( 'username', 'password' ) - .withIndexPermalinks() + .withIndexPermalinks() .create(); const productRepository = VariableProduct.restRepository( httpClient ); From 771548f852e606cd48defdd3c0b0b8bca8cf4fa3 Mon Sep 17 00:00:00 2001 From: Timmy Crawford Date: Wed, 12 May 2021 08:47:08 -0700 Subject: [PATCH 26/42] Update woocommerce-admin package to 2.3.0 --- bin/composer/mozart/composer.lock | 52 +++++++++++------------ bin/composer/phpcs/composer.lock | 10 ++--- bin/composer/wp/composer.lock | 70 ++++++++++++++++++------------- composer.json | 2 +- composer.lock | 19 +++++---- 5 files changed, 84 insertions(+), 69 deletions(-) diff --git a/bin/composer/mozart/composer.lock b/bin/composer/mozart/composer.lock index 6e9a52a1179..81ac1cea0fc 100644 --- a/bin/composer/mozart/composer.lock +++ b/bin/composer/mozart/composer.lock @@ -267,16 +267,16 @@ }, { "name": "symfony/console", - "version": "v5.2.6", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d" + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/35f039df40a3b335ebf310f244cb242b3a83ac8d", - "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d", + "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", "shasum": "" }, "require": { @@ -344,7 +344,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.6" + "source": "https://github.com/symfony/console/tree/v5.2.8" }, "funding": [ { @@ -360,20 +360,20 @@ "type": "tidelift" } ], - "time": "2021-03-28T09:42:18+00:00" + "time": "2021-05-11T15:45:21+00:00" }, { "name": "symfony/finder", - "version": "v5.2.4", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "0d639a0943822626290d169965804f79400e6a04" + "reference": "eccb8be70d7a6a2230d05f6ecede40f3fdd9e252" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/0d639a0943822626290d169965804f79400e6a04", - "reference": "0d639a0943822626290d169965804f79400e6a04", + "url": "https://api.github.com/repos/symfony/finder/zipball/eccb8be70d7a6a2230d05f6ecede40f3fdd9e252", + "reference": "eccb8be70d7a6a2230d05f6ecede40f3fdd9e252", "shasum": "" }, "require": { @@ -405,7 +405,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.2.4" + "source": "https://github.com/symfony/finder/tree/v5.2.8" }, "funding": [ { @@ -421,7 +421,7 @@ "type": "tidelift" } ], - "time": "2021-02-15T18:55:04+00:00" + "time": "2021-05-10T14:39:23+00:00" }, { "name": "symfony/polyfill-ctype", @@ -911,21 +911,21 @@ }, { "name": "symfony/service-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/container": "^1.0" + "psr/container": "^1.1" }, "suggest": { "symfony/service-implementation": "" @@ -933,7 +933,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -970,7 +970,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/master" + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" }, "funding": [ { @@ -986,20 +986,20 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-04-01T10:43:52+00:00" }, { "name": "symfony/string", - "version": "v5.2.6", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572" + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", "shasum": "" }, "require": { @@ -1053,7 +1053,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.6" + "source": "https://github.com/symfony/string/tree/v5.2.8" }, "funding": [ { @@ -1069,7 +1069,7 @@ "type": "tidelift" } ], - "time": "2021-03-17T17:12:15+00:00" + "time": "2021-05-10T14:56:10+00:00" } ], "aliases": [], diff --git a/bin/composer/phpcs/composer.lock b/bin/composer/phpcs/composer.lock index d784a60a0a0..e0653d55467 100644 --- a/bin/composer/phpcs/composer.lock +++ b/bin/composer/phpcs/composer.lock @@ -251,16 +251,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.8", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", "shasum": "" }, "require": { @@ -303,7 +303,7 @@ "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2020-10-23T02:01:07+00:00" + "time": "2021-04-09T00:54:41+00:00" }, { "name": "woocommerce/woocommerce-sniffs", diff --git a/bin/composer/wp/composer.lock b/bin/composer/wp/composer.lock index 8fb33475e13..3532eb3520e 100644 --- a/bin/composer/wp/composer.lock +++ b/bin/composer/wp/composer.lock @@ -254,23 +254,30 @@ }, { "name": "rmccue/requests", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", - "url": "https://github.com/rmccue/Requests.git", - "reference": "87932f52ffad70504d93f04f15690cf16a089546" + "url": "https://github.com/WordPress/Requests.git", + "reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rmccue/Requests/zipball/87932f52ffad70504d93f04f15690cf16a089546", - "reference": "87932f52ffad70504d93f04f15690cf16a089546", + "url": "https://api.github.com/repos/WordPress/Requests/zipball/afbe4790e4def03581c4a0963a1e8aa01f6030f1", + "reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1", "shasum": "" }, "require": { "php": ">=5.2" }, "require-dev": { - "requests/test-server": "dev-master" + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "php-parallel-lint/php-console-highlighter": "^0.5.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5", + "requests/test-server": "dev-master", + "squizlabs/php_codesniffer": "^3.5", + "wp-coding-standards/wpcs": "^2.0" }, "type": "library", "autoload": { @@ -289,7 +296,7 @@ } ], "description": "A HTTP library written in PHP, for human beings.", - "homepage": "http://github.com/rmccue/Requests", + "homepage": "http://github.com/WordPress/Requests", "keywords": [ "curl", "fsockopen", @@ -300,10 +307,10 @@ "sockets" ], "support": { - "issues": "https://github.com/rmccue/Requests/issues", - "source": "https://github.com/rmccue/Requests/tree/master" + "issues": "https://github.com/WordPress/Requests/issues", + "source": "https://github.com/WordPress/Requests/tree/v1.8.0" }, - "time": "2016-10-13T00:11:37+00:00" + "time": "2021-04-27T11:05:25+00:00" }, { "name": "symfony/finder", @@ -359,26 +366,26 @@ }, { "name": "wp-cli/i18n-command", - "version": "v2.2.6", + "version": "v2.2.8", "source": { "type": "git", "url": "https://github.com/wp-cli/i18n-command.git", - "reference": "a66da3f09f6a728832381012848c3074bf1635c8" + "reference": "8bc234617edc533590ac0f41080164a8d85ec9ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/a66da3f09f6a728832381012848c3074bf1635c8", - "reference": "a66da3f09f6a728832381012848c3074bf1635c8", + "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/8bc234617edc533590ac0f41080164a8d85ec9ce", + "reference": "8bc234617edc533590ac0f41080164a8d85ec9ce", "shasum": "" }, "require": { "gettext/gettext": "^4.8", "mck89/peast": "^1.8", - "wp-cli/wp-cli": "^2" + "wp-cli/wp-cli": "^2.5" }, "require-dev": { "wp-cli/scaffold-command": "^1.2 || ^2", - "wp-cli/wp-cli-tests": "^2.1.3" + "wp-cli/wp-cli-tests": "^3.0.11" }, "type": "wp-cli-package", "extra": { @@ -414,9 +421,9 @@ "homepage": "https://github.com/wp-cli/i18n-command", "support": { "issues": "https://github.com/wp-cli/i18n-command/issues", - "source": "https://github.com/wp-cli/i18n-command/tree/v2.2.6" + "source": "https://github.com/wp-cli/i18n-command/tree/v2.2.8" }, - "time": "2020-12-07T19:28:27+00:00" + "time": "2021-05-10T10:24:16+00:00" }, { "name": "wp-cli/mustangostang-spyc", @@ -525,23 +532,23 @@ }, { "name": "wp-cli/wp-cli", - "version": "v2.4.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/wp-cli/wp-cli.git", - "reference": "ceb18598e79befa9b2a37a51efbb34910628988b" + "reference": "4c4746d06640af7698f3792cc4c327a8482dc40f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/ceb18598e79befa9b2a37a51efbb34910628988b", - "reference": "ceb18598e79befa9b2a37a51efbb34910628988b", + "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/4c4746d06640af7698f3792cc4c327a8482dc40f", + "reference": "4c4746d06640af7698f3792cc4c327a8482dc40f", "shasum": "" }, "require": { "ext-curl": "*", "mustache/mustache": "~2.13", - "php": "^5.4 || ^7.0", - "rmccue/requests": "~1.6", + "php": "^5.6 || ^7.0 || ^8.0", + "rmccue/requests": "^1.8", "symfony/finder": ">2.7", "wp-cli/mustangostang-spyc": "^0.6.3", "wp-cli/php-cli-tools": "~0.11.2" @@ -552,12 +559,13 @@ "wp-cli/entity-command": "^1.2 || ^2", "wp-cli/extension-command": "^1.1 || ^2", "wp-cli/package-command": "^1 || ^2", - "wp-cli/wp-cli-tests": "^2.1" + "wp-cli/wp-cli-tests": "^3.0.7" }, "suggest": { "ext-readline": "Include for a better --prompt implementation", "ext-zip": "Needed to support extraction of ZIP archives when doing downloads or updates" }, + "default-branch": true, "bin": [ "bin/wp", "bin/wp.bat" @@ -565,13 +573,17 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4.x-dev" + "dev-master": "2.5.x-dev" } }, "autoload": { "psr-0": { - "WP_CLI": "php" - } + "WP_CLI\\": "php/" + }, + "classmap": [ + "php/class-wp-cli.php", + "php/class-wp-cli-command.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -588,7 +600,7 @@ "issues": "https://github.com/wp-cli/wp-cli/issues", "source": "https://github.com/wp-cli/wp-cli" }, - "time": "2020-02-18T08:15:37+00:00" + "time": "2021-05-13T09:36:33+00:00" } ], "aliases": [], diff --git a/composer.json b/composer.json index 6346176de2a..34a1dc6a246 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "pelago/emogrifier": "3.1.0", "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", - "woocommerce/woocommerce-admin": "2.2.6", + "woocommerce/woocommerce-admin": "2.3.0", "woocommerce/woocommerce-blocks": "5.1.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 16af2df5a8d..966a06ec993 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3f82e5bd9e485ba6bcd94111391f6f11", + "content-hash": "ac338dadb8929c73ad9606426621f9ba", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -532,16 +532,16 @@ }, { "name": "woocommerce/woocommerce-admin", - "version": "2.2.6", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8" + "reference": "c690969d301ddb7145b43e72e4dd99c84cc8ba66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8", - "reference": "65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/c690969d301ddb7145b43e72e4dd99c84cc8ba66", + "reference": "c690969d301ddb7145b43e72e4dd99c84cc8ba66", "shasum": "" }, "require": { @@ -550,7 +550,7 @@ "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "7.5.20", + "bamarni/composer-bin-plugin": "^1.4", "suin/phpcs-psr4-sniff": "^2.2", "woocommerce/woocommerce-sniffs": "0.1.0" }, @@ -560,6 +560,9 @@ "test": "Run unit tests", "phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer", "phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier" + }, + "bamarni-bin": { + "target-directory": "bin/composer" } }, "autoload": { @@ -575,9 +578,9 @@ "homepage": "https://github.com/woocommerce/woocommerce-admin", "support": { "issues": "https://github.com/woocommerce/woocommerce-admin/issues", - "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.2.6" + "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.3.0" }, - "time": "2021-05-07T21:29:02+00:00" + "time": "2021-05-12T15:20:07+00:00" }, { "name": "woocommerce/woocommerce-blocks", From bee633cef7fcc7eabd6f24fa3bc5b8e04133e674 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Fri, 14 May 2021 12:49:55 -0300 Subject: [PATCH 27/42] Update delete all to include trash (#29881) * update stale to Stale in feedback label CI * delete trashed objects, use api to delete imported products * restore two lines deleted in merge --- .../wp-admin-product-import-csv.test.js | 17 ++++++------ tests/e2e/utils/src/flows/with-rest-api.js | 26 +++++++++++-------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js b/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js index e3705010a93..1e2b945ad24 100644 --- a/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js +++ b/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js @@ -5,7 +5,7 @@ const { merchant, setCheckbox, - moveAllItemsToTrash + withRestApi, } = require( '@woocommerce/e2e-utils' ); const getCoreTestsRoot = require( '../../core-tests-root' ); @@ -108,10 +108,12 @@ const runImportProductsTest = () => { // Gathering product names await page.waitForSelector('a.row-title'); - const productTitles = await page.$$eval('a.row-title', - elements => elements.map(item => item.innerHTML)); + const productTitles = await page.$$eval( + 'a.row-title', + elements => elements.map(item => item.innerHTML) + ); - // Compare overriden product names + // Compare overridden product names expect(productTitles.sort()).toEqual(productNamesOverride.sort()); // Gathering product prices @@ -119,12 +121,11 @@ const runImportProductsTest = () => { const productPrices = await page.$$eval('.amount', elements => elements.map(item => item.innerText)); - // Compare overriden product prices + // Compare overridden product prices expect(productPrices.sort()).toEqual(productPricesOverride.sort()); - // Move all imported products to trash - await moveAllItemsToTrash(); - + // Delete imported products + await withRestApi.deleteAllProducts(); }); }); }; diff --git a/tests/e2e/utils/src/flows/with-rest-api.js b/tests/e2e/utils/src/flows/with-rest-api.js index 442d1d20a8c..52b6648f6a0 100644 --- a/tests/e2e/utils/src/flows/with-rest-api.js +++ b/tests/e2e/utils/src/flows/with-rest-api.js @@ -16,20 +16,24 @@ const userEndpoint = '/wp/v2/users'; const deleteAllRepositoryObjects = async ( repository, defaultObjectId = null ) => { let objects; const minimum = defaultObjectId == null ? 0 : 1; + const statuses = ['publish','trash']; - objects = await repository.list(); - while ( objects.length > minimum ) { - for (let o = 0; o < objects.length; o++ ) { - // Skip default data store object - if ( objects[ o ].id == defaultObjectId ) { - continue; + for ( let s = 0; s < statuses.length; s++ ) { + const status = statuses[ s ]; + objects = await repository.list( { status } ); + while (objects.length > minimum) { + for (let o = 0; o < objects.length; o++) { + // Skip default data store object + if (objects[o].id == defaultObjectId) { + continue; + } + // We may be getting a cached copy of the dataset and the object has already been deleted. + try { + await repository.delete(objects[o].id); + } catch (e) {} } - // We may be getting a cached copy of the dataset and the object has already been deleted. - try { - await repository.delete(objects[o].id); - } catch (e) {} + objects = await repository.list( { status } ); } - objects = await repository.list(); } }; From 661aa38b6be9e65d23b9cb0745bf84734a1a2b2f Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Fri, 14 May 2021 13:26:30 -0500 Subject: [PATCH 28/42] REST API: Update date_query usage in CRUS controller to be consistent, and generate an array of queries --- .../Controllers/Version3/class-wc-rest-crud-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php b/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php index 2ebf47a1eab..310bd2367e0 100644 --- a/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php +++ b/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php @@ -303,7 +303,7 @@ abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller { // Check flag to use post_date vs post_date_gmt. if ( true === $request['dates_are_gmt'] ) { if ( isset( $request['before'] ) || isset( $request['after'] ) ) { - $args['date_query']['column'] = 'post_date_gmt'; + $args['date_query'][0]['column'] = 'post_date_gmt'; } } From 9f6104598ba70425177a058f024cb98724c34e82 Mon Sep 17 00:00:00 2001 From: roykho Date: Fri, 14 May 2021 12:06:07 -0700 Subject: [PATCH 29/42] Set header cache-control for cart/checkout pages closes #29484 --- includes/class-wc-cache-helper.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-cache-helper.php b/includes/class-wc-cache-helper.php index f07fca63eb0..fddf46aef33 100644 --- a/includes/class-wc-cache-helper.php +++ b/includes/class-wc-cache-helper.php @@ -42,14 +42,34 @@ class WC_Cache_Helper { */ public static function additional_nocache_headers( $headers ) { $agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + + $set_cache = false; + /** * Allow plugins to enable nocache headers. Enabled for Google weblight. * - * @see https://support.google.com/webmasters/answer/1061943?hl=en * @param bool $enable_nocache_headers Flag indicating whether to add nocache headers. Default: false. */ - if ( false !== strpos( $agent, 'googleweblight' ) || apply_filters( 'woocommerce_enable_nocache_headers', false ) ) { + if ( apply_filters( 'woocommerce_enable_nocache_headers', false ) ) { + $set_cache = true; + } + + /** + * Enabled for Google weblight. + * + * @see https://support.google.com/webmasters/answer/1061943?hl=en + */ + if ( false !== strpos( $agent, 'googleweblight' ) ) { // no-transform: Opt-out of Google weblight. https://support.google.com/webmasters/answer/6211428?hl=en. + $set_cache = true; + } + + // Note that is_cart() will return true even for checkout page. + if ( false !== strpos( $agent, 'Chrome' ) && is_cart() ) { + $set_cache = true; + } + + if ( $set_cache ) { $headers['Cache-Control'] = 'no-transform, no-cache, no-store, must-revalidate'; } return $headers; From 82404d467bd56af459e547e8bd894f9da1f04820 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Fri, 14 May 2021 16:53:46 -0300 Subject: [PATCH 30/42] package lock maintenance for version bump --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c5d1334562..679d985d486 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "woocommerce", - "version": "5.3.0", + "version": "5.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -9308,7 +9308,7 @@ } }, "prettier": { - "version": "npm:wp-prettier@1.19.1", + "version": "npm:prettier@1.19.1", "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-1.19.1.tgz", "integrity": "sha512-mqAC2r1NDmRjG+z3KCJ/i61tycKlmADIjxnDhQab+KBxSAGbF/W7/zwB2guy/ypIeKrrftNsIYkNZZQKf3vJcg==", "dev": true From 92d3bdfacb58c4a2dfdf82f507c1b1232f36ceee Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Fri, 14 May 2021 16:59:50 -0300 Subject: [PATCH 31/42] add draft status to deleteAllObjects --- tests/e2e/utils/src/flows/with-rest-api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/utils/src/flows/with-rest-api.js b/tests/e2e/utils/src/flows/with-rest-api.js index 52b6648f6a0..64b40d773ee 100644 --- a/tests/e2e/utils/src/flows/with-rest-api.js +++ b/tests/e2e/utils/src/flows/with-rest-api.js @@ -16,7 +16,7 @@ const userEndpoint = '/wp/v2/users'; const deleteAllRepositoryObjects = async ( repository, defaultObjectId = null ) => { let objects; const minimum = defaultObjectId == null ? 0 : 1; - const statuses = ['publish','trash']; + const statuses = ['draft','publish','trash']; for ( let s = 0; s < statuses.length; s++ ) { const status = statuses[ s ]; From 657d84ae3ef306895f1bd7ee5616515a659a9f14 Mon Sep 17 00:00:00 2001 From: Christopher Allford <6451942+ObliviousHarmony@users.noreply.github.com> Date: Fri, 14 May 2021 14:08:30 -0700 Subject: [PATCH 32/42] Revert "Fix filter woocommerce_shipping_rate_cost backwards compatibility" --- includes/class-wc-tax.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/includes/class-wc-tax.php b/includes/class-wc-tax.php index bf6956e6639..a59f60cc4de 100644 --- a/includes/class-wc-tax.php +++ b/includes/class-wc-tax.php @@ -82,13 +82,7 @@ class WC_Tax { * @return array */ public static function calc_shipping_tax( $price, $rates ) { - // Backwards compatible from WC_Shipping_Rate::get_cost(). - if ( has_filter( 'woocommerce_shipping_rate_cost' ) ) { - $rate = new WC_Shipping_Rate(); - $price = $rate->get_cost(); - } $taxes = self::calc_exclusive_tax( $price, $rates ); - return apply_filters( 'woocommerce_calc_shipping_tax', $taxes, $price, $rates ); } From 0b89a27abd31f49a7c73a0b6c11fe51329a4c1eb Mon Sep 17 00:00:00 2001 From: Christopher Allford <6451942+ObliviousHarmony@users.noreply.github.com> Date: Fri, 14 May 2021 15:03:39 -0700 Subject: [PATCH 33/42] Updated versions for 5.5.0 development --- includes/class-woocommerce.php | 2 +- package-lock.json | 2 +- package.json | 2 +- woocommerce.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/class-woocommerce.php b/includes/class-woocommerce.php index e4586ebbf66..89fd66fee90 100644 --- a/includes/class-woocommerce.php +++ b/includes/class-woocommerce.php @@ -25,7 +25,7 @@ final class WooCommerce { * * @var string */ - public $version = '5.3.0'; + public $version = '5.5.0'; /** * WooCommerce Schema version. diff --git a/package-lock.json b/package-lock.json index 679d985d486..92b593f6ebb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "woocommerce", - "version": "5.4.0", + "version": "5.5.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 00559ae31f1..3c9b50a16e1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "woocommerce", "title": "WooCommerce", - "version": "5.4.0", + "version": "5.5.0", "homepage": "https://woocommerce.com/", "repository": { "type": "git", diff --git a/woocommerce.php b/woocommerce.php index 1fb1516fb43..57edd900f95 100644 --- a/woocommerce.php +++ b/woocommerce.php @@ -3,7 +3,7 @@ * Plugin Name: WooCommerce * Plugin URI: https://woocommerce.com/ * Description: An eCommerce toolkit that helps you sell anything. Beautifully. - * Version: 5.4.0-dev + * Version: 5.5.0-dev * Author: Automattic * Author URI: https://woocommerce.com * Text Domain: woocommerce From aa7e77a8edd9a3bea6152f0e9b6cbef0a690812b Mon Sep 17 00:00:00 2001 From: roykho Date: Mon, 17 May 2021 12:50:38 -0700 Subject: [PATCH 34/42] Remove comment that it includes checkout page --- includes/class-wc-cache-helper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/class-wc-cache-helper.php b/includes/class-wc-cache-helper.php index fddf46aef33..4a9c0604eab 100644 --- a/includes/class-wc-cache-helper.php +++ b/includes/class-wc-cache-helper.php @@ -64,7 +64,6 @@ class WC_Cache_Helper { $set_cache = true; } - // Note that is_cart() will return true even for checkout page. if ( false !== strpos( $agent, 'Chrome' ) && is_cart() ) { $set_cache = true; } From 90443914f09d11972700ec7f36485f06276f23d4 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 4 May 2021 01:03:13 -0500 Subject: [PATCH 35/42] Set checkout field value with defined default --- includes/class-wc-checkout.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index 036c4ba612c..b5a4990a164 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -686,27 +686,32 @@ class WC_Checkout { } foreach ( $fieldset as $key => $field ) { + if ( isset( $_POST[ $key ] ) ) { // phpcs:disable WordPress.Security.NonceVerification.Missing + $value = wp_unslash( $_POST[ $key ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + } elseif ( isset( $field['default'] ) ) { + $value = $field['default']; + } else { + $value = ''; + } + $type = sanitize_title( isset( $field['type'] ) ? $field['type'] : 'text' ); - // phpcs:disable WordPress.Security.NonceVerification.Missing switch ( $type ) { case 'checkbox': - $value = isset( $_POST[ $key ] ) ? 1 : ''; + $value = 1; break; case 'multiselect': - $value = isset( $_POST[ $key ] ) ? implode( ', ', wc_clean( wp_unslash( $_POST[ $key ] ) ) ) : ''; + $value = implode( ', ', wc_clean( $value ) ); break; case 'textarea': - $value = isset( $_POST[ $key ] ) ? wc_sanitize_textarea( wp_unslash( $_POST[ $key ] ) ) : ''; + $value = wc_sanitize_textarea( $value ); break; case 'password': - $value = isset( $_POST[ $key ] ) ? wp_unslash( $_POST[ $key ] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized break; default: - $value = isset( $_POST[ $key ] ) ? wc_clean( wp_unslash( $_POST[ $key ] ) ) : ''; + $value = wc_clean( $value ); break; } - // phpcs:enable WordPress.Security.NonceVerification.Missing $data[ $key ] = apply_filters( 'woocommerce_process_checkout_' . $type . '_field', apply_filters( 'woocommerce_process_checkout_field_' . $key, $value ) ); } From 5a5a8081825fc6605b46877747007d97f5a5f4eb Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Thu, 6 May 2021 15:14:14 -0500 Subject: [PATCH 36/42] Update syntax to ignore line from PHP CodeSniffer --- includes/class-wc-checkout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index b5a4990a164..d750f7e3f0c 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -1128,7 +1128,7 @@ class WC_Checkout { */ public function process_checkout() { try { - $nonce_value = wc_get_var( $_REQUEST['woocommerce-process-checkout-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine. + $nonce_value = wc_get_var( $_REQUEST['woocommerce-process-checkout-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // phpcs:ignore if ( empty( $nonce_value ) || ! wp_verify_nonce( $nonce_value, 'woocommerce-process_checkout' ) ) { WC()->session->set( 'refresh_totals', true ); From 195acd0866c70cccd9de7a9ccde9a14f8c0fd58f Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 10 May 2021 14:54:40 -0500 Subject: [PATCH 37/42] Skip switch statement if value is empty --- includes/class-wc-checkout.php | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index d750f7e3f0c..31670f6d7f4 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -696,21 +696,23 @@ class WC_Checkout { $type = sanitize_title( isset( $field['type'] ) ? $field['type'] : 'text' ); - switch ( $type ) { - case 'checkbox': - $value = 1; - break; - case 'multiselect': - $value = implode( ', ', wc_clean( $value ) ); - break; - case 'textarea': - $value = wc_sanitize_textarea( $value ); - break; - case 'password': - break; - default: - $value = wc_clean( $value ); - break; + if ( '' !== $value ) { + switch ( $type ) { + case 'checkbox': + $value = 1; + break; + case 'multiselect': + $value = implode( ', ', wc_clean( $value ) ); + break; + case 'textarea': + $value = wc_sanitize_textarea( $value ); + break; + case 'password': + break; + default: + $value = wc_clean( $value ); + break; + } } $data[ $key ] = apply_filters( 'woocommerce_process_checkout_' . $type . '_field', apply_filters( 'woocommerce_process_checkout_field_' . $key, $value ) ); From c7bd6805792d8c16100546afc0d33f4603319870 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 11 May 2021 14:12:51 -0500 Subject: [PATCH 38/42] Consolidate value for checkbox input types --- includes/class-wc-checkout.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index 31670f6d7f4..264eed60a0b 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -685,11 +685,13 @@ class WC_Checkout { continue; } + $is_checkout_page = isset( $_REQUEST['woocommerce-process-checkout-nonce'] ); + foreach ( $fieldset as $key => $field ) { if ( isset( $_POST[ $key ] ) ) { // phpcs:disable WordPress.Security.NonceVerification.Missing $value = wp_unslash( $_POST[ $key ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized - } elseif ( isset( $field['default'] ) ) { - $value = $field['default']; + } elseif ( isset( $field['default'] ) && ! $is_checkout_page ) { + $value = '1' === (string) $field['default'] ? 1 : ''; } else { $value = ''; } From 32566c508e24b729afb7bba2067f31b83202ae9c Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 12 May 2021 13:34:18 -0500 Subject: [PATCH 39/42] Consolidate value for checkbox input types --- includes/class-wc-checkout.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index 264eed60a0b..045aba056a1 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -688,16 +688,16 @@ class WC_Checkout { $is_checkout_page = isset( $_REQUEST['woocommerce-process-checkout-nonce'] ); foreach ( $fieldset as $key => $field ) { - if ( isset( $_POST[ $key ] ) ) { // phpcs:disable WordPress.Security.NonceVerification.Missing + $type = sanitize_title( isset( $field['type'] ) ? $field['type'] : 'text' ); + + if ( isset( $_POST[ $key ] ) && '' !== $_POST[ $key ] ) { // phpcs:disable WordPress.Security.NonceVerification.Missing $value = wp_unslash( $_POST[ $key ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized - } elseif ( isset( $field['default'] ) && ! $is_checkout_page ) { - $value = '1' === (string) $field['default'] ? 1 : ''; + } elseif ( isset( $field['default'] ) && 'checkbox' !== $type ) { + $value = $field['default']; } else { $value = ''; } - $type = sanitize_title( isset( $field['type'] ) ? $field['type'] : 'text' ); - if ( '' !== $value ) { switch ( $type ) { case 'checkbox': From 79db2d95a0a8beacbb73f6d116967e15e5ca372b Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 17 May 2021 17:15:16 -0500 Subject: [PATCH 40/42] Use default value only if form was displayed to the user Also changed variable name for readability --- includes/class-wc-checkout.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index 045aba056a1..ef46e957905 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -685,14 +685,14 @@ class WC_Checkout { continue; } - $is_checkout_page = isset( $_REQUEST['woocommerce-process-checkout-nonce'] ); + $form_was_shown = isset( $_REQUEST['woocommerce-process-checkout-nonce'] ); foreach ( $fieldset as $key => $field ) { $type = sanitize_title( isset( $field['type'] ) ? $field['type'] : 'text' ); if ( isset( $_POST[ $key ] ) && '' !== $_POST[ $key ] ) { // phpcs:disable WordPress.Security.NonceVerification.Missing $value = wp_unslash( $_POST[ $key ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized - } elseif ( isset( $field['default'] ) && 'checkbox' !== $type ) { + } elseif ( isset( $field['default'] ) && 'checkbox' !== $type && ! $form_was_shown ) { $value = $field['default']; } else { $value = ''; From f20e8ab567f611fceb4b05d41b658c232a398288 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 17 May 2021 18:26:16 -0500 Subject: [PATCH 41/42] Move variable declaration outside foreach loop --- includes/class-wc-checkout.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index ef46e957905..6909110edeb 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -679,14 +679,14 @@ class WC_Checkout { // phpcs:enable WordPress.Security.NonceVerification.Missing $skipped = array(); + $form_was_shown = isset( $_POST['woocommerce-process-checkout-nonce'] ); + foreach ( $this->get_checkout_fields() as $fieldset_key => $fieldset ) { if ( $this->maybe_skip_fieldset( $fieldset_key, $data ) ) { $skipped[] = $fieldset_key; continue; } - $form_was_shown = isset( $_REQUEST['woocommerce-process-checkout-nonce'] ); - foreach ( $fieldset as $key => $field ) { $type = sanitize_title( isset( $field['type'] ) ? $field['type'] : 'text' ); From 8fa6265ef7b791439adc22e27cb56fa0abf2383e Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 17 May 2021 18:35:18 -0500 Subject: [PATCH 42/42] Fix Code Sniffer error --- includes/class-wc-checkout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index 6909110edeb..3133be81505 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -679,7 +679,7 @@ class WC_Checkout { // phpcs:enable WordPress.Security.NonceVerification.Missing $skipped = array(); - $form_was_shown = isset( $_POST['woocommerce-process-checkout-nonce'] ); + $form_was_shown = isset( $_POST['woocommerce-process-checkout-nonce'] ); // phpcs:disable WordPress.Security.NonceVerification.Missing foreach ( $this->get_checkout_fields() as $fieldset_key => $fieldset ) { if ( $this->maybe_skip_fieldset( $fieldset_key, $data ) ) {