Implement PHP DI container and refactor. Also implements new Asset data interface for extendable settings passed to js. (https://github.com/woocommerce/woocommerce-blocks/pull/956)
* Add dependency injection container for blocks * Add new Pacakge and Bootstrap classes. - Bootstrap for bootstrapping the plugin. - Package will replace `src/Package` and added as a dependency for any classes needing package info. * Introduce AssetsDataRegistry for managing asset data * refactor existing classes to use new DIC and Asset Data Registry - this is the bare minimum needed to make this pull viable. - further refactors will be done in more atomic smaller pulls for easier review. * add new settings handling and export `@woocommerce/settings` as an alias to wc.wcSettings - the export is exposed php side on the `wc-settings` handle. * Remove unnecessary concatenation * Fix typos and improve doc blocks * fix php linting issue * Use better escaping function. * improve jsdoc spacing * improve test assertion * use fully qualified class names in bootstrap * improve comment block to account for dynamic version string replace on build * handle exceptions a bit differently * correct dependency reference in webpack config * remove blank lines * fix doc block comment alignment * Various doc/grammar/spacing fixes from code review. Co-Authored-By: Albert Juhé Lluveras <contact@albertjuhe.com> * improve naming, documentation and logic of filter callbacks While this is intended for sanitization/validation, the callback ultimately provides flexibility for filtering the value before returning or setting in state so `filter` is a better name for this.
This commit is contained in:
parent
574b5230d9
commit
57fdb8fe9c
|
@ -4,19 +4,11 @@ module.exports = {
|
||||||
'jest/globals': true,
|
'jest/globals': true,
|
||||||
},
|
},
|
||||||
globals: {
|
globals: {
|
||||||
wc_product_block_data: true,
|
|
||||||
wcSettings: true,
|
wcSettings: true,
|
||||||
},
|
},
|
||||||
plugins: [ 'jest' ],
|
plugins: [ 'jest' ],
|
||||||
rules: {
|
rules: {
|
||||||
'@wordpress/dependency-group': 'off',
|
'@wordpress/dependency-group': 'off',
|
||||||
camelcase: [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
allow: [ 'wc_product_block_data' ],
|
|
||||||
properties: 'never',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'valid-jsdoc': 'off',
|
'valid-jsdoc': 'off',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { getSetting } from '@woocommerce/settings';
|
||||||
|
|
||||||
|
export const ENABLE_REVIEW_RATING = getSetting( 'enableReviewRating', true );
|
||||||
|
export const SHOW_AVATARS = getSetting( 'showAvatars', true );
|
||||||
|
export const MAX_COLUMNS = getSetting( 'max_columns', 6 );
|
||||||
|
export const MIN_COLUMNS = getSetting( 'min_columns', 1 );
|
||||||
|
export const DEFAULT_COLUMNS = getSetting( 'default_columns', 3 );
|
||||||
|
export const MAX_ROWS = getSetting( 'max_rows', 6 );
|
||||||
|
export const MIN_ROWS = getSetting( 'min_rows', 1 );
|
||||||
|
export const DEFAULT_ROWS = getSetting( 'default_rows', 1 );
|
||||||
|
export const MIN_HEIGHT = getSetting( 'min_height', 500 );
|
||||||
|
export const DEFAULT_HEIGHT = getSetting( 'default_height', 500 );
|
||||||
|
export const PLACEHOLDER_IMG_SRC = getSetting( 'placeholderImgSrc ', '' );
|
||||||
|
export const THUMBNAIL_SIZE = getSetting( 'thumbnail_size', 300 );
|
||||||
|
export const IS_LARGE_CATALOG = getSetting( 'isLargeCatalog' );
|
||||||
|
export const LIMIT_TAGS = getSetting( 'limitTags' );
|
||||||
|
export const HAS_TAGS = getSetting( 'hasTags', true );
|
||||||
|
export const HOME_URL = getSetting( 'homeUrl ', '' );
|
||||||
|
export const PRODUCT_CATEGORIES = getSetting( 'productCategories', [] );
|
|
@ -1,37 +1,2 @@
|
||||||
const getConstantFromData = ( property, fallback = false ) => {
|
export * from './constants';
|
||||||
if (
|
|
||||||
typeof wc_product_block_data === 'object' &&
|
|
||||||
wc_product_block_data.hasOwnProperty( property )
|
|
||||||
) {
|
|
||||||
return wc_product_block_data[ property ];
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ENABLE_REVIEW_RATING = getConstantFromData(
|
|
||||||
'enableReviewRating',
|
|
||||||
true
|
|
||||||
);
|
|
||||||
export const SHOW_AVATARS = getConstantFromData( 'showAvatars', true );
|
|
||||||
export const MAX_COLUMNS = getConstantFromData( 'max_columns', 6 );
|
|
||||||
export const MIN_COLUMNS = getConstantFromData( 'min_columns', 1 );
|
|
||||||
export const DEFAULT_COLUMNS = getConstantFromData( 'default_columns', 3 );
|
|
||||||
export const MAX_ROWS = getConstantFromData( 'max_rows', 6 );
|
|
||||||
export const MIN_ROWS = getConstantFromData( 'min_rows', 1 );
|
|
||||||
export const DEFAULT_ROWS = getConstantFromData( 'default_rows', 1 );
|
|
||||||
export const MIN_HEIGHT = getConstantFromData( 'min_height', 500 );
|
|
||||||
export const DEFAULT_HEIGHT = getConstantFromData( 'default_height', 500 );
|
|
||||||
export const PLACEHOLDER_IMG_SRC = getConstantFromData(
|
|
||||||
'placeholderImgSrc ',
|
|
||||||
''
|
|
||||||
);
|
|
||||||
export const THUMBNAIL_SIZE = getConstantFromData( 'thumbnail_size', 300 );
|
|
||||||
export const IS_LARGE_CATALOG = getConstantFromData( 'isLargeCatalog' );
|
|
||||||
export const LIMIT_TAGS = getConstantFromData( 'limitTags' );
|
|
||||||
export const HAS_TAGS = getConstantFromData( 'hasTags', true );
|
|
||||||
export const HOME_URL = getConstantFromData( 'homeUrl ', '' );
|
|
||||||
export const PRODUCT_CATEGORIES = getConstantFromData(
|
|
||||||
'productCategories',
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
export { ENDPOINTS } from './endpoints';
|
export { ENDPOINTS } from './endpoints';
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
/**
|
|
||||||
* Wrapper for the wcSettings global, which sets defaults if data is missing.
|
|
||||||
*
|
|
||||||
* Only settings used by blocks are defined here. Component settings are left out.
|
|
||||||
*/
|
|
||||||
const currency = wcSettings.currency || {
|
|
||||||
code: 'USD',
|
|
||||||
precision: 2,
|
|
||||||
symbol: '$',
|
|
||||||
position: 'left',
|
|
||||||
decimal_separator: '.',
|
|
||||||
thousand_separator: ',',
|
|
||||||
price_format: '%1$s%2$s',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default currency;
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { allSettings } from './settings-init';
|
||||||
|
|
||||||
|
export const ADMIN_URL = allSettings.adminUrl;
|
||||||
|
export const COUNTRIES = allSettings.countries;
|
||||||
|
export const CURRENCY = allSettings.currency;
|
||||||
|
export const LOCALE = allSettings.locale;
|
||||||
|
export const ORDER_STATUSES = allSettings.orderStatuses;
|
||||||
|
export const SITE_TITLE = allSettings.siteTitle;
|
||||||
|
export const WC_ASSET_URL = allSettings.wcAssetUrl;
|
||||||
|
export const DEFAULT_DATE_RANGE = allSettings.defaultDateRange;
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { allSettings } from './settings-init';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a setting value from the setting state.
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {string} name The identifier for the setting.
|
||||||
|
* @param {mixed} [fallback=false] The value to use as a fallback
|
||||||
|
* if the setting is not in the
|
||||||
|
* state.
|
||||||
|
* @param {function} [filter=( val ) => val] A callback for filtering the
|
||||||
|
* value before it's returned.
|
||||||
|
* Receives both the found value
|
||||||
|
* (if it exists for the key) and
|
||||||
|
* the provided fallback arg.
|
||||||
|
* @returns {mixed}
|
||||||
|
*/
|
||||||
|
export function getSetting( name, fallback = false, filter = ( val ) => val ) {
|
||||||
|
const value = allSettings.hasOwnProperty( name )
|
||||||
|
? allSettings[ name ]
|
||||||
|
: fallback;
|
||||||
|
return filter( value, fallback );
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
// Exports shared settings from wcSettings global.
|
export { getSetting } from './get-setting';
|
||||||
export { default as currency } from './currency';
|
export { setSetting } from './set-setting';
|
||||||
|
export * from './default-constants';
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { allSettings } from './settings-init';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a value to a property on the settings state.
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {string} name The setting property key for the
|
||||||
|
* setting being mutated.
|
||||||
|
* @param {mixed} value The value to set.
|
||||||
|
* @param {function} [filter=( val ) => val] Allows for providing a callback
|
||||||
|
* to sanitize the setting (eg.
|
||||||
|
* ensure it's a number)
|
||||||
|
*/
|
||||||
|
export function setSetting( name, value, filter = ( val ) => val ) {
|
||||||
|
value = filter( value );
|
||||||
|
allSettings[ name ] = filter( value );
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
const defaults = {
|
||||||
|
adminUrl: '',
|
||||||
|
countries: [],
|
||||||
|
currency: {
|
||||||
|
code: 'USD',
|
||||||
|
precision: 2,
|
||||||
|
symbol: '$',
|
||||||
|
symbolPosition: 'left',
|
||||||
|
decimalSeparator: '.',
|
||||||
|
priceFormat: '%1$s%2$s',
|
||||||
|
thousandSeparator: ',',
|
||||||
|
},
|
||||||
|
defaultDateRange: 'period=month&compare=previous_year',
|
||||||
|
locale: {
|
||||||
|
siteLocale: 'en_US',
|
||||||
|
userLocale: 'en_US',
|
||||||
|
weekdaysShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
|
||||||
|
},
|
||||||
|
orderStatuses: [],
|
||||||
|
siteTitle: '',
|
||||||
|
wcAssetUrl: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const globalSharedSettings = typeof wcSettings === 'object' ? wcSettings : {};
|
||||||
|
|
||||||
|
// Use defaults or global settings, depending on what is set.
|
||||||
|
const allSettings = {
|
||||||
|
...defaults,
|
||||||
|
...globalSharedSettings,
|
||||||
|
};
|
||||||
|
|
||||||
|
allSettings.currency = {
|
||||||
|
...defaults.currency,
|
||||||
|
...allSettings.currency,
|
||||||
|
};
|
||||||
|
|
||||||
|
allSettings.locale = {
|
||||||
|
...defaults.locale,
|
||||||
|
...allSettings.locale,
|
||||||
|
};
|
||||||
|
|
||||||
|
export { allSettings };
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { getSetting } from '../get-setting';
|
||||||
|
import { ADMIN_URL } from '../default-constants';
|
||||||
|
|
||||||
|
describe( 'getSetting', () => {
|
||||||
|
it( 'returns provided default for non available setting', () => {
|
||||||
|
expect( getSetting( 'nada', 'really nada' ) ).toBe( 'really nada' );
|
||||||
|
} );
|
||||||
|
it( 'returns expected value for existing setting', () => {
|
||||||
|
expect( getSetting( 'adminUrl', 'not this' ) ).toEqual( ADMIN_URL );
|
||||||
|
} );
|
||||||
|
it( 'filters value via provided filter callback', () => {
|
||||||
|
expect( getSetting( 'some value', 'default', () => 42 ) ).toBe( 42 );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { setSetting } from '../set-setting';
|
||||||
|
import { getSetting } from '../get-setting';
|
||||||
|
|
||||||
|
describe( 'setSetting', () => {
|
||||||
|
it( 'should add a new value to the settings state for value not present', () => {
|
||||||
|
setSetting( 'aSetting', 42 );
|
||||||
|
expect( getSetting( 'aSetting' ) ).toBe( 42 );
|
||||||
|
} );
|
||||||
|
it( 'should replace existing value', () => {
|
||||||
|
setSetting( 'adminUrl', 'not original' );
|
||||||
|
expect( getSetting( 'adminUrl' ) ).toBe( 'not original' );
|
||||||
|
} );
|
||||||
|
it( 'should save the value run through the provided filter', () => {
|
||||||
|
setSetting( 'aSetting', 'who', () => 42 );
|
||||||
|
expect( getSetting( 'aSetting' ) ).toBe( 42 );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -16,19 +16,23 @@ class Assets {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize class features on init.
|
* Initialize class features on init.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
* Moved most initialization to BootStrap and AssetDataRegistry
|
||||||
|
* classes as a part of ongoing refactor
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
add_action( 'init', array( __CLASS__, 'register_assets' ) );
|
add_action( 'init', array( __CLASS__, 'register_assets' ) );
|
||||||
add_action( 'admin_print_scripts', array( __CLASS__, 'print_shared_settings' ), 1 );
|
|
||||||
add_action( 'admin_print_scripts', array( __CLASS__, 'maybe_add_asset_data' ), 1 );
|
|
||||||
add_action( 'admin_print_footer_scripts', array( __CLASS__, 'maybe_add_asset_data' ), 1 );
|
|
||||||
add_action( 'wp_print_scripts', array( __CLASS__, 'maybe_add_asset_data' ), 1 );
|
|
||||||
add_action( 'wp_print_footer_scripts', array( __CLASS__, 'maybe_add_asset_data' ), 1 );
|
|
||||||
add_action( 'body_class', array( __CLASS__, 'add_theme_body_class' ), 1 );
|
add_action( 'body_class', array( __CLASS__, 'add_theme_body_class' ), 1 );
|
||||||
|
add_filter( 'woocommerce_shared_settings', array( __CLASS__, 'get_wc_block_data' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register block scripts & styles.
|
* Register block scripts & styles.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
* Moved data related enqueuing to new AssetDataRegistry class
|
||||||
|
* as part of ongoing refactoring.
|
||||||
*/
|
*/
|
||||||
public static function register_assets() {
|
public static function register_assets() {
|
||||||
self::register_style( 'wc-block-editor', plugins_url( 'build/editor.css', __DIR__ ), array( 'wp-edit-blocks' ) );
|
self::register_style( 'wc-block-editor', plugins_url( 'build/editor.css', __DIR__ ), array( 'wp-edit-blocks' ) );
|
||||||
|
@ -37,10 +41,8 @@ class Assets {
|
||||||
wp_style_add_data( 'wc-block-style', 'rtl', 'replace' );
|
wp_style_add_data( 'wc-block-style', 'rtl', 'replace' );
|
||||||
|
|
||||||
// Shared libraries and components across all blocks.
|
// Shared libraries and components across all blocks.
|
||||||
self::register_script( 'wc-shared-settings', plugins_url( 'build/wc-shared-settings.js', __DIR__ ), [], false );
|
|
||||||
self::register_script( 'wc-block-settings', plugins_url( 'build/wc-block-settings.js', __DIR__ ), [], false );
|
|
||||||
self::register_script( 'wc-blocks', plugins_url( 'build/blocks.js', __DIR__ ), [], false );
|
self::register_script( 'wc-blocks', plugins_url( 'build/blocks.js', __DIR__ ), [], false );
|
||||||
self::register_script( 'wc-vendors', plugins_url( 'build/vendors.js', __DIR__ ), [ 'wc-shared-settings' ], false );
|
self::register_script( 'wc-vendors', plugins_url( 'build/vendors.js', __DIR__ ), [], false );
|
||||||
|
|
||||||
// Individual blocks.
|
// Individual blocks.
|
||||||
self::register_script( 'wc-handpicked-products', plugins_url( 'build/handpicked-products.js', __DIR__ ), array( 'wc-vendors', 'wc-blocks' ) );
|
self::register_script( 'wc-handpicked-products', plugins_url( 'build/handpicked-products.js', __DIR__ ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||||
|
@ -60,30 +62,6 @@ class Assets {
|
||||||
self::register_script( 'wc-product-search', plugins_url( 'build/product-search.js', __DIR__ ), array( 'wc-vendors', 'wc-blocks' ) );
|
self::register_script( 'wc-product-search', plugins_url( 'build/product-search.js', __DIR__ ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Print wcSettings in all pages. This is a temporary fix until we find a better
|
|
||||||
* solution to share settings between WooCommerce Admin and WooCommerce Blocks.
|
|
||||||
* See https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/932
|
|
||||||
*/
|
|
||||||
public static function print_shared_settings() {
|
|
||||||
echo '<script>';
|
|
||||||
echo "var wcSettings = wcSettings || JSON.parse( decodeURIComponent( '" . esc_js( self::get_wc_settings_data() ) . "' ) );";
|
|
||||||
echo '</script>';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attach data to registered assets using inline scripts.
|
|
||||||
*/
|
|
||||||
public static function maybe_add_asset_data() {
|
|
||||||
if ( wp_script_is( 'wc-block-settings', 'enqueued' ) ) {
|
|
||||||
wp_add_inline_script(
|
|
||||||
'wc-block-settings',
|
|
||||||
self::get_wc_block_data(),
|
|
||||||
'before'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add body classes.
|
* Add body classes.
|
||||||
*
|
*
|
||||||
|
@ -95,50 +73,17 @@ class Assets {
|
||||||
return $classes;
|
return $classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns javascript to inject as data for enqueued wc-shared-settings script.
|
|
||||||
*
|
|
||||||
* @return string;
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
protected static function get_wc_settings_data() {
|
|
||||||
global $wp_locale;
|
|
||||||
$code = get_woocommerce_currency();
|
|
||||||
$settings = apply_filters(
|
|
||||||
'woocommerce_components_settings',
|
|
||||||
array(
|
|
||||||
'adminUrl' => admin_url(),
|
|
||||||
'wcAssetUrl' => plugins_url( 'assets/', WC_PLUGIN_FILE ),
|
|
||||||
'siteLocale' => esc_attr( get_bloginfo( 'language' ) ),
|
|
||||||
'currency' => array(
|
|
||||||
'code' => $code,
|
|
||||||
'precision' => wc_get_price_decimals(),
|
|
||||||
'symbol' => html_entity_decode( get_woocommerce_currency_symbol( $code ) ),
|
|
||||||
'position' => get_option( 'woocommerce_currency_pos' ),
|
|
||||||
'decimal_separator' => wc_get_price_decimal_separator(),
|
|
||||||
'thousand_separator' => wc_get_price_thousand_separator(),
|
|
||||||
'price_format' => html_entity_decode( get_woocommerce_price_format() ),
|
|
||||||
),
|
|
||||||
'stockStatuses' => wc_get_product_stock_status_options(),
|
|
||||||
'siteTitle' => get_bloginfo( 'name' ),
|
|
||||||
'dataEndpoints' => [],
|
|
||||||
'l10n' => array(
|
|
||||||
'userLocale' => get_user_locale(),
|
|
||||||
'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return rawurlencode( wp_json_encode( $settings ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns block-related data for enqueued wc-block-settings script.
|
* Returns block-related data for enqueued wc-block-settings script.
|
||||||
*
|
*
|
||||||
* This is used to map site settings & data into JS-accessible variables.
|
* This is used to map site settings & data into JS-accessible variables.
|
||||||
*
|
*
|
||||||
|
* @param array $settings The original settings array from the filter.
|
||||||
|
*
|
||||||
* @since 2.4.0
|
* @since 2.4.0
|
||||||
|
* @since $VID:$ returned merged data along with incoming $settings
|
||||||
*/
|
*/
|
||||||
protected static function get_wc_block_data() {
|
public static function get_wc_block_data( $settings ) {
|
||||||
$tag_count = wp_count_terms( 'product_tag' );
|
$tag_count = wp_count_terms( 'product_tag' );
|
||||||
$product_counts = wp_count_posts( 'product' );
|
$product_counts = wp_count_posts( 'product' );
|
||||||
$product_categories = get_terms(
|
$product_categories = get_terms(
|
||||||
|
@ -153,7 +98,9 @@ class Assets {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global settings used in each block.
|
// Global settings used in each block.
|
||||||
$block_settings = array(
|
return array_merge(
|
||||||
|
$settings,
|
||||||
|
[
|
||||||
'min_columns' => wc_get_theme_support( 'product_blocks::min_columns', 1 ),
|
'min_columns' => wc_get_theme_support( 'product_blocks::min_columns', 1 ),
|
||||||
'max_columns' => wc_get_theme_support( 'product_blocks::max_columns', 6 ),
|
'max_columns' => wc_get_theme_support( 'product_blocks::max_columns', 6 ),
|
||||||
'default_columns' => wc_get_theme_support( 'product_blocks::default_columns', 3 ),
|
'default_columns' => wc_get_theme_support( 'product_blocks::default_columns', 3 ),
|
||||||
|
@ -168,12 +115,11 @@ class Assets {
|
||||||
'limitTags' => $tag_count > 100,
|
'limitTags' => $tag_count > 100,
|
||||||
'hasTags' => $tag_count > 0,
|
'hasTags' => $tag_count > 0,
|
||||||
'productCategories' => $product_categories,
|
'productCategories' => $product_categories,
|
||||||
'homeUrl' => esc_js( home_url( '/' ) ),
|
'homeUrl' => esc_url( home_url( '/' ) ),
|
||||||
'showAvatars' => '1' === get_option( 'show_avatars' ),
|
'showAvatars' => '1' === get_option( 'show_avatars' ),
|
||||||
'enableReviewRating' => 'yes' === get_option( 'woocommerce_enable_review_rating' ),
|
'enableReviewRating' => 'yes' === get_option( 'woocommerce_enable_review_rating' ),
|
||||||
|
]
|
||||||
);
|
);
|
||||||
$block_settings = rawurlencode( wp_json_encode( $block_settings ) );
|
|
||||||
return "var wc_product_block_data = JSON.parse( decodeURIComponent( '" . $block_settings . "' ) );";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Contains asset api methods
|
||||||
|
*
|
||||||
|
* @package WooCommerce/Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Assets;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Domain\Package;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Api class provides an interface to various asset registration helpers.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class Api {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the Package instance
|
||||||
|
*
|
||||||
|
* @var Package
|
||||||
|
*/
|
||||||
|
private $package;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for class
|
||||||
|
*
|
||||||
|
* @param Package $package An instance of Package.
|
||||||
|
*/
|
||||||
|
public function __construct( Package $package ) {
|
||||||
|
$this->package = $package;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the file modified time as a cache buster if we're in dev mode.
|
||||||
|
*
|
||||||
|
* @param string $file Local path to the file (relative to the plugin
|
||||||
|
* directory).
|
||||||
|
* @return string The cache buster value to use for the given file.
|
||||||
|
*/
|
||||||
|
protected function get_file_version( $file ) {
|
||||||
|
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
||||||
|
return filemtime( $this->package->get_path( trim( $file, '/' ) ) );
|
||||||
|
}
|
||||||
|
return $this->package->get_version();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the url to an asset for this plugin.
|
||||||
|
*
|
||||||
|
* @param string $relative_path An optional relative path appended to the
|
||||||
|
* returned url.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_asset_url( $relative_path = '' ) {
|
||||||
|
return $this->package->get_url( $relative_path );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the dependency array for the given asset relative path.
|
||||||
|
*
|
||||||
|
* @param string $asset_relative_path Something like 'build/constants.js'
|
||||||
|
* considered to be relative to the main
|
||||||
|
* asset path.
|
||||||
|
* @param array $extra_dependencies Extra dependencies to be explicitly
|
||||||
|
* added to the generated array.
|
||||||
|
*
|
||||||
|
* @return array An array of dependencies
|
||||||
|
*/
|
||||||
|
protected function get_dependencies(
|
||||||
|
$asset_relative_path,
|
||||||
|
$extra_dependencies = []
|
||||||
|
) {
|
||||||
|
$dependency_path = $this->package->get_path(
|
||||||
|
str_replace( '.js', '.deps.json', $asset_relative_path )
|
||||||
|
);
|
||||||
|
// phpcs:ignore WordPress.WP.AlternativeFunctions
|
||||||
|
$dependencies = file_exists( $dependency_path )
|
||||||
|
// phpcs:ignore WordPress.WP.AlternativeFunctions
|
||||||
|
? json_decode( file_get_contents( $dependency_path ) )
|
||||||
|
: [];
|
||||||
|
return array_merge( $dependencies, $extra_dependencies );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a script according to `wp_register_script`, additionally
|
||||||
|
* loading the translations for the file.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*
|
||||||
|
* @param string $handle Name of the script. Should be unique.
|
||||||
|
* @param string $relative_src Relative url for the script to the path
|
||||||
|
* from plugin root.
|
||||||
|
* @param array $deps Optional. An array of registered script
|
||||||
|
* handles this script depends on. Default
|
||||||
|
* empty array.
|
||||||
|
* @param bool $has_i18n Optional. Whether to add a script
|
||||||
|
* translation call to this file. Default:
|
||||||
|
* true.
|
||||||
|
*/
|
||||||
|
public function register_script( $handle, $relative_src, $deps = [], $has_i18n = true ) {
|
||||||
|
wp_register_script(
|
||||||
|
$handle,
|
||||||
|
$this->get_asset_url( $relative_src ),
|
||||||
|
$this->get_dependencies( $relative_src, $deps ),
|
||||||
|
$this->get_file_version( $relative_src ),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if ( $has_i18n && function_exists( 'wp_set_script_translations' ) ) {
|
||||||
|
wp_set_script_translations(
|
||||||
|
$handle,
|
||||||
|
'woo-gutenberg-products-block',
|
||||||
|
$this->package->get_path( 'languages' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues a block script.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*
|
||||||
|
* @param string $name Name of the script used to identify the file inside build folder.
|
||||||
|
*/
|
||||||
|
public function register_block_script( $name ) {
|
||||||
|
$src = 'build/' . $name . '.js';
|
||||||
|
$handle = 'wc-' . $name;
|
||||||
|
$this->register_script( $handle, $src );
|
||||||
|
wp_enqueue_script( $handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a style according to `wp_register_style`.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*
|
||||||
|
* @param string $handle Name of the stylesheet. Should be unique.
|
||||||
|
* @param string $src Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
|
||||||
|
* @param array $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array.
|
||||||
|
* @param string $media Optional. The media for which this stylesheet has been defined. Default 'all'. Accepts media types like
|
||||||
|
* 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'.
|
||||||
|
*/
|
||||||
|
public function register_style( $handle, $src, $deps = [], $media = 'all' ) {
|
||||||
|
$filename = str_replace( plugins_url( '/', __DIR__ ), '', $src );
|
||||||
|
$ver = $this->get_file_version( $filename );
|
||||||
|
wp_register_style( $handle, $src, $deps, $ver, $media );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,268 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Holds data registered for output on the current view session when
|
||||||
|
* `wc-settings` is enqueued (directly or via dependency)
|
||||||
|
*
|
||||||
|
* @package WooCommerce/Blocks
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Assets;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class instance for registering data used on the current view session by
|
||||||
|
* assets.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class AssetDataRegistry {
|
||||||
|
/**
|
||||||
|
* Contains registered data.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $data = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazy data is an array of closures that will be invoked just before
|
||||||
|
* asset data is generated for the enqueued script.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $lazy_data = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asset handle for registered data.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $handle = 'wc-settings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asset API interface for various asset registration.
|
||||||
|
*
|
||||||
|
* @var API
|
||||||
|
*/
|
||||||
|
private $api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param Api $asset_api Asset API interface for various asset registration.
|
||||||
|
*/
|
||||||
|
public function __construct( Api $asset_api ) {
|
||||||
|
$this->api = $asset_api;
|
||||||
|
$this->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into WP asset registration for enqueueing asset data.
|
||||||
|
*/
|
||||||
|
protected function init() {
|
||||||
|
add_action( 'init', array( $this, 'register_data_script' ) );
|
||||||
|
add_action( 'wp_print_footer_scripts', array( $this, 'enqueue_asset_data' ), 1 );
|
||||||
|
add_action( 'admin_print_footer_scripts', array( $this, 'enqueue_asset_data' ), 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes core asset data
|
||||||
|
*
|
||||||
|
* @return array An array containing core data.
|
||||||
|
*/
|
||||||
|
protected function get_core_data() {
|
||||||
|
global $wp_locale;
|
||||||
|
$currency = get_woocommerce_currency();
|
||||||
|
return [
|
||||||
|
'adminUrl' => admin_url(),
|
||||||
|
'countries' => WC()->countries->get_countries(),
|
||||||
|
'currency' => [
|
||||||
|
'code' => $currency,
|
||||||
|
'precision' => wc_get_price_decimals(),
|
||||||
|
'symbol' => html_entity_decode( get_woocommerce_currency_symbol( $currency ) ),
|
||||||
|
'symbolPosition' => get_option( 'woocommerce_currency_pos' ),
|
||||||
|
'decimalSeparator' => wc_get_price_decimal_separator(),
|
||||||
|
'thousandSeparator' => wc_get_price_thousand_separator(),
|
||||||
|
'priceFormat' => html_entity_decode( get_woocommerce_price_format() ),
|
||||||
|
],
|
||||||
|
'locale' => [
|
||||||
|
'siteLocale' => get_locale(),
|
||||||
|
'userLocale' => get_user_locale(),
|
||||||
|
'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ),
|
||||||
|
],
|
||||||
|
'orderStatuses' => $this->get_order_statuses( wc_get_order_statuses() ),
|
||||||
|
'siteTitle' => get_bloginfo( 'name ' ),
|
||||||
|
'wcAssetUrl' => plugins_url( 'assets/', WC_PLUGIN_FILE ),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns block-related data for enqueued wc-settings script.
|
||||||
|
* Format order statuses by removing a leading 'wc-' if present.
|
||||||
|
*
|
||||||
|
* @param array $statuses Order statuses.
|
||||||
|
* @return array formatted statuses.
|
||||||
|
*/
|
||||||
|
protected function get_order_statuses( $statuses ) {
|
||||||
|
$formatted_statuses = array();
|
||||||
|
foreach ( $statuses as $key => $value ) {
|
||||||
|
$formatted_key = preg_replace( '/^wc-/', '', $key );
|
||||||
|
$formatted_statuses[ $formatted_key ] = $value;
|
||||||
|
}
|
||||||
|
return $formatted_statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for on demand initialization of asset data and registering it with
|
||||||
|
* the internal data registry.
|
||||||
|
*
|
||||||
|
* Note: core data will overwrite any externally registered data via the api.
|
||||||
|
*/
|
||||||
|
protected function initialize_core_data() {
|
||||||
|
/**
|
||||||
|
* Low level hook for registration of new data late in the cycle.
|
||||||
|
*
|
||||||
|
* Developers, do not use this hook as it is likely to be removed.
|
||||||
|
* Instead, use the data api:
|
||||||
|
* wc_blocks_container()
|
||||||
|
* ->get( Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry::class )
|
||||||
|
* ->add( $key, $value )
|
||||||
|
*/
|
||||||
|
$settings = apply_filters(
|
||||||
|
'woocommerce_shared_settings',
|
||||||
|
$this->data
|
||||||
|
);
|
||||||
|
// note this WILL wipe any data already registered to these keys because
|
||||||
|
// they are protected.
|
||||||
|
$this->data = array_merge_recursive( $settings, $this->get_core_data() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loops through each registered lazy data callback and adds the returned
|
||||||
|
* value to the data array.
|
||||||
|
*
|
||||||
|
* This method is executed right before preparing the data for printing to
|
||||||
|
* the rendered screen.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function execute_lazy_data() {
|
||||||
|
foreach ( $this->lazy_data as $key => $callback ) {
|
||||||
|
$this->data[ $key ] = $callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes private registered data to child classes.
|
||||||
|
*
|
||||||
|
* @return array The registered data on the private data property
|
||||||
|
*/
|
||||||
|
protected function get() {
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for adding data to the registry.
|
||||||
|
*
|
||||||
|
* @param string $key The key used to reference the data being registered.
|
||||||
|
* You can only register data that is not already in the
|
||||||
|
* registry identified by the given key.
|
||||||
|
* @param mixed $data If not a function, registered to the registry as is.
|
||||||
|
* If a function, then the callback is invoked right
|
||||||
|
* before output to the screen.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException Only throws when site is in debug mode.
|
||||||
|
* Always logs the error.
|
||||||
|
*/
|
||||||
|
public function add( $key, $data ) {
|
||||||
|
try {
|
||||||
|
$this->add_data( $key, $data );
|
||||||
|
} catch ( Exception $e ) {
|
||||||
|
if ( $this->debug() ) {
|
||||||
|
// bubble up.
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
wc_caught_exception( $e, __METHOD__, [ $key, $data ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for registering the data script via WordPress API.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register_data_script() {
|
||||||
|
$this->api->register_script(
|
||||||
|
$this->handle,
|
||||||
|
'build/wc-settings.js',
|
||||||
|
[],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for enqueuing asset data via the WP api.
|
||||||
|
*
|
||||||
|
* Note: while this is hooked into print/admin_print_scripts, it still only
|
||||||
|
* happens if the script attached to `wc-settings` handle is enqueued. This
|
||||||
|
* is done to allow for any potentially expensive data generation to only
|
||||||
|
* happen for routes that need it.
|
||||||
|
*/
|
||||||
|
public function enqueue_asset_data() {
|
||||||
|
if ( wp_script_is( $this->handle, 'enqueued' ) ) {
|
||||||
|
$this->initialize_core_data();
|
||||||
|
$this->execute_lazy_data();
|
||||||
|
$data = rawurlencode( wp_json_encode( $this->data ) );
|
||||||
|
wp_add_inline_script(
|
||||||
|
$this->handle,
|
||||||
|
"var wcSettings = wcSettings || JSON.parse( decodeURIComponent( '"
|
||||||
|
. esc_js( $data )
|
||||||
|
. "' ) );",
|
||||||
|
'before'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See self::add() for docs.
|
||||||
|
*
|
||||||
|
* @param string $key Key for the data.
|
||||||
|
* @param mixed $data Value for the data.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If key is not a string or already
|
||||||
|
* exists in internal data cache.
|
||||||
|
*/
|
||||||
|
protected function add_data( $key, $data ) {
|
||||||
|
if ( ! is_string( $key ) ) {
|
||||||
|
if ( $this->debug() ) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'Key for the data being registered must be a string'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( isset( $this->data[ $key ] ) ) {
|
||||||
|
if ( $this->debug() ) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'Overriding existing data with an already registered key is not allowed'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( \method_exists( $data, '__invoke' ) ) {
|
||||||
|
$this->lazy_data[ $key ] = $data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->data[ $key ] = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes whether the current site is in debug mode or not.
|
||||||
|
*
|
||||||
|
* @return boolean True means the site is in debug mode.
|
||||||
|
*/
|
||||||
|
protected function debug() {
|
||||||
|
return defined( 'WP_DEBUG' ) && WP_DEBUG;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Backwards Compatibility file for plugins using wcSettings in prior versions
|
||||||
|
*
|
||||||
|
* @package WooCommerce/Blocks
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Assets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backwards Compatibility class for plugins using wcSettings in prior versions.
|
||||||
|
*
|
||||||
|
* Note: This will be removed at some point.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class BackCompatAssetDataRegistry extends AssetDataRegistry {
|
||||||
|
/**
|
||||||
|
* Overrides parent method.
|
||||||
|
*
|
||||||
|
* @see AssetDataRegistry::enqueue_asset_data
|
||||||
|
*/
|
||||||
|
public function enqueue_asset_data() {
|
||||||
|
$this->initialize_core_data();
|
||||||
|
$this->execute_lazy_data();
|
||||||
|
/**
|
||||||
|
* Back-compat filter, developers, use 'woocommerce_shared_settings'
|
||||||
|
* filter, not this one.
|
||||||
|
*
|
||||||
|
* @deprecated $VID:$
|
||||||
|
*/
|
||||||
|
$data = apply_filters(
|
||||||
|
'woocommerce_components_settings',
|
||||||
|
$this->get()
|
||||||
|
);
|
||||||
|
|
||||||
|
$data = rawurlencode( wp_json_encode( $data ) );
|
||||||
|
// for back compat with wc-admin (or other plugins) that expects
|
||||||
|
// wcSettings to be always available.
|
||||||
|
// @see https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/932.
|
||||||
|
echo '<script>';
|
||||||
|
echo "var wcSettings = wcSettings || JSON.parse( decodeURIComponent( '" . esc_js( $data ) . "' ) );";
|
||||||
|
echo '</script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override parent method.
|
||||||
|
*
|
||||||
|
* @see AssetDataRegistry::get_core_data
|
||||||
|
*
|
||||||
|
* @return array An array of data to output for enqueued script.
|
||||||
|
*/
|
||||||
|
protected function get_core_data() {
|
||||||
|
global $wp_locale;
|
||||||
|
$core_data = parent::get_core_data();
|
||||||
|
return array_merge(
|
||||||
|
$core_data,
|
||||||
|
[
|
||||||
|
'siteLocale' => $core_data['locale']['siteLocale'],
|
||||||
|
'stockStatuses' => $core_data['orderStatuses'],
|
||||||
|
'dataEndpoints' => [],
|
||||||
|
'l10n' => [
|
||||||
|
'userLocale' => $core_data['locale']['userLocale'],
|
||||||
|
'weekdaysShort' => $core_data['locale']['weekdaysShort'],
|
||||||
|
],
|
||||||
|
'currency' => array_merge(
|
||||||
|
$core_data['currency'],
|
||||||
|
[
|
||||||
|
'position' => $core_data['currency']['symbolPosition'],
|
||||||
|
'decimal_separator' => $core_data['currency']['decimalSeparator'],
|
||||||
|
'thousand_separator' => $core_data['currency']['thousandSeparator'],
|
||||||
|
'price_format' => $core_data['currency']['priceFormat'],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Contains the Bootstrap class
|
||||||
|
*
|
||||||
|
* @package WooCommerce/Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Domain;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Assets as OldAssets;
|
||||||
|
use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi;
|
||||||
|
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
|
||||||
|
use Automattic\WooCommerce\Blocks\Assets\BackCompatAssetDataRegistry;
|
||||||
|
use Automattic\WooCommerce\Blocks\Library;
|
||||||
|
use Automattic\WooCommerce\Blocks\Registry\Container;
|
||||||
|
use Automattic\WooCommerce\Blocks\RestApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes care of bootstrapping the plugin.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class Bootstrap {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the Dependency Injection Container
|
||||||
|
*
|
||||||
|
* @var Container
|
||||||
|
*/
|
||||||
|
private $container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the Package instance
|
||||||
|
*
|
||||||
|
* @var Package
|
||||||
|
*/
|
||||||
|
private $package;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param Container $container The Dependency Injection Container.
|
||||||
|
*/
|
||||||
|
public function __construct( Container $container ) {
|
||||||
|
$this->container = $container;
|
||||||
|
$this->package = $container->get( Package::class );
|
||||||
|
$this->init();
|
||||||
|
/**
|
||||||
|
* Usable as a safe event hook for when the plugin has been loaded.
|
||||||
|
*/
|
||||||
|
do_action( 'woocommerce_blocks_loaded' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init the package - load the blocks library and define constants.
|
||||||
|
*/
|
||||||
|
public function init() {
|
||||||
|
if ( ! $this->has_dependencies() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->remove_core_blocks();
|
||||||
|
|
||||||
|
if ( ! $this->is_built() ) {
|
||||||
|
$this->add_build_notice();
|
||||||
|
}
|
||||||
|
|
||||||
|
// register core dependencies with the container.
|
||||||
|
$this->container->register(
|
||||||
|
AssetApi::class,
|
||||||
|
function ( Container $container ) {
|
||||||
|
return new AssetApi( $container->get( Package::class ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$this->container->register(
|
||||||
|
AssetDataRegistry::class,
|
||||||
|
function( Container $container ) {
|
||||||
|
$asset_api = $container->get( AssetApi::class );
|
||||||
|
$load_back_compat = (
|
||||||
|
defined( 'WC_ADMIN_VERSION_NUMBER' )
|
||||||
|
&& version_compare( WC_ADMIN_VERSION_NUMBER, '0.19.0', '<=' )
|
||||||
|
) ||
|
||||||
|
(
|
||||||
|
version_compare( WC_VERSION, '3.7.0', '<=' )
|
||||||
|
);
|
||||||
|
return $load_back_compat
|
||||||
|
? new BackCompatAssetDataRegistry( $asset_api )
|
||||||
|
: new AssetDataRegistry( $asset_api );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// load AssetDataRegistry.
|
||||||
|
$this->container->get( AssetDataRegistry::class );
|
||||||
|
|
||||||
|
Library::init();
|
||||||
|
OldAssets::init();
|
||||||
|
RestApi::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check dependencies exist.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function has_dependencies() {
|
||||||
|
return class_exists( 'WooCommerce' ) && function_exists( 'register_block_type' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See if files have been built or not.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function is_built() {
|
||||||
|
return file_exists(
|
||||||
|
$this->package->get_path( 'build/featured-product.js' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a notice stating that the build has not been done yet.
|
||||||
|
*/
|
||||||
|
protected function add_build_notice() {
|
||||||
|
add_action(
|
||||||
|
'admin_notices',
|
||||||
|
function() {
|
||||||
|
echo '<div class="error"><p>';
|
||||||
|
printf(
|
||||||
|
/* Translators: %1$s is the install command, %2$s is the build command, %3$s is the watch command. */
|
||||||
|
esc_html__( 'WooCommerce Blocks development mode requires files to be built. From the plugin directory, run %1$s to install dependencies, %2$s to build the files or %3$s to build the files and watch for changes.', 'woo-gutenberg-products-block' ),
|
||||||
|
'<code>npm install</code>',
|
||||||
|
'<code>npm run build</code>',
|
||||||
|
'<code>npm start</code>'
|
||||||
|
);
|
||||||
|
echo '</p></div>';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove core blocks (for 3.6 and above).
|
||||||
|
*/
|
||||||
|
protected function remove_core_blocks() {
|
||||||
|
remove_action( 'init', array( 'WC_Block_Library', 'init' ) );
|
||||||
|
remove_action( 'init', array( 'WC_Block_Library', 'register_blocks' ) );
|
||||||
|
remove_action( 'init', array( 'WC_Block_Library', 'register_assets' ) );
|
||||||
|
remove_filter( 'block_categories', array( 'WC_Block_Library', 'add_block_category' ) );
|
||||||
|
remove_action( 'admin_print_footer_scripts', array( 'WC_Block_Library', 'print_script_settings' ), 1 );
|
||||||
|
remove_action( 'init', array( 'WGPB_Block_Library', 'init' ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Returns information about the package and handles init.
|
||||||
|
*
|
||||||
|
* @package WooCommerce/Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main package class.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class Package {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the current version for the plugin.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the main path to the plugin directory.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the path to the main plugin file (entry)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $plugin_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $version Version of the plugin.
|
||||||
|
* @param string $plugin_file Path to the main plugin file.
|
||||||
|
*/
|
||||||
|
public function __construct( $version, $plugin_file ) {
|
||||||
|
$this->version = $version;
|
||||||
|
$this->plugin_file = $plugin_file;
|
||||||
|
$this->path = dirname( $plugin_file );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version of the plugin.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_version() {
|
||||||
|
return $this->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path to the main plugin file.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_plugin_file() {
|
||||||
|
return $this->plugin_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path to the plugin directory.
|
||||||
|
*
|
||||||
|
* @param string $relative_path If provided, the relative path will be
|
||||||
|
* appended to the plugin path.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_path( $relative_path = '' ) {
|
||||||
|
return '' === $relative_path
|
||||||
|
? trailingslashit( $this->path )
|
||||||
|
: trailingslashit( $this->path ) . $relative_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the url to the plugin directory.
|
||||||
|
*
|
||||||
|
* @param string $relative_url If provided, the relative url will be
|
||||||
|
* appended to the plugin url.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_url( $relative_url = '' ) {
|
||||||
|
return '' === $relative_url
|
||||||
|
? plugin_dir_url( $this->get_plugin_file() )
|
||||||
|
: plugin_dir_url( $this->get_plugin_file() ) . $relative_url;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,45 +7,36 @@
|
||||||
|
|
||||||
namespace Automattic\WooCommerce\Blocks;
|
namespace Automattic\WooCommerce\Blocks;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Domain\Package as NewPackage;
|
||||||
|
|
||||||
defined( 'ABSPATH' ) || exit;
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main package class.
|
* Main package class.
|
||||||
|
*
|
||||||
|
* @deprecated $VID:$
|
||||||
*/
|
*/
|
||||||
class Package {
|
class Package {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version.
|
* For back compat this is provided. Ideally, you should register your
|
||||||
|
* class with Automattic\Woocommerce\Blocks\Container and make Package a
|
||||||
|
* dependency.
|
||||||
*
|
*
|
||||||
* @var string
|
* @since $VID:$
|
||||||
|
* @return Package The Package instance class
|
||||||
*/
|
*/
|
||||||
const VERSION = '2.5.0-dev';
|
protected static function get_package() {
|
||||||
|
return wc_blocks_container()->get( NewPackage::class );
|
||||||
/**
|
}
|
||||||
* Stores if init has ran yet.
|
|
||||||
*
|
|
||||||
* @var boolean
|
|
||||||
*/
|
|
||||||
protected static $did_init = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init the package - load the blocks library and define constants.
|
* Init the package - load the blocks library and define constants.
|
||||||
|
*
|
||||||
|
* @since $VID:$ Handled by new NewPackage.
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
if ( true === self::$did_init || ! self::has_dependencies() ) {
|
// noop.
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$did_init = true;
|
|
||||||
self::remove_core_blocks();
|
|
||||||
|
|
||||||
if ( ! self::is_built() ) {
|
|
||||||
self::add_build_notice();
|
|
||||||
}
|
|
||||||
|
|
||||||
Library::init();
|
|
||||||
Assets::init();
|
|
||||||
RestApi::init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +45,7 @@ class Package {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function get_version() {
|
public static function get_version() {
|
||||||
return self::VERSION;
|
return self::get_package()->get_version();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,57 +54,6 @@ class Package {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function get_path() {
|
public static function get_path() {
|
||||||
return dirname( __DIR__ );
|
return self::get_package()->get_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check dependencies exist.
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
protected static function has_dependencies() {
|
|
||||||
return class_exists( 'WooCommerce' ) && function_exists( 'register_block_type' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See if files have been built or not.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected static function is_built() {
|
|
||||||
return file_exists( dirname( __DIR__ ) . '/build/featured-product.js' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a notice stating that the build has not been done yet.
|
|
||||||
*/
|
|
||||||
protected static function add_build_notice() {
|
|
||||||
add_action(
|
|
||||||
'admin_notices',
|
|
||||||
function() {
|
|
||||||
echo '<div class="error"><p>';
|
|
||||||
printf(
|
|
||||||
/* Translators: %1$s is the install command, %2$s is the build command, %3$s is the watch command. */
|
|
||||||
esc_html__( 'WooCommerce Blocks development mode requires files to be built. From the plugin directory, run %1$s to install dependencies, %2$s to build the files or %3$s to build the files and watch for changes.', 'woo-gutenberg-products-block' ),
|
|
||||||
'<code>npm install</code>',
|
|
||||||
'<code>npm run build</code>',
|
|
||||||
'<code>npm start</code>'
|
|
||||||
);
|
|
||||||
echo '</p></div>';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove core blocks (for 3.6 and below).
|
|
||||||
*/
|
|
||||||
protected static function remove_core_blocks() {
|
|
||||||
remove_action( 'init', array( 'WC_Block_Library', 'init' ) );
|
|
||||||
remove_action( 'init', array( 'WC_Block_Library', 'register_blocks' ) );
|
|
||||||
remove_action( 'init', array( 'WC_Block_Library', 'register_assets' ) );
|
|
||||||
remove_filter( 'block_categories', array( 'WC_Block_Library', 'add_block_category' ) );
|
|
||||||
remove_action( 'admin_print_footer_scripts', array( 'WC_Block_Library', 'print_script_settings' ), 1 );
|
|
||||||
remove_action( 'init', array( 'WGPB_Block_Library', 'init' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Holds the AbstractDependencyType class.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Registry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract class for dependency types.
|
||||||
|
*
|
||||||
|
* Dependency types are instances of a dependency used by the
|
||||||
|
* Dependency Injection Container for storing dependencies to invoke as they
|
||||||
|
* are needed.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
abstract class AbstractDependencyType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds a callable or value provided for this type.
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $callable_or_value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param mixed $callable_or_value A callable or value for the dependency
|
||||||
|
* type instance.
|
||||||
|
*/
|
||||||
|
public function __construct( $callable_or_value ) {
|
||||||
|
$this->callable_or_value = $callable_or_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolver for the internal dependency value.
|
||||||
|
*
|
||||||
|
* @param Container $container The Dependency Injection Container.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function resolve_value( Container $container ) {
|
||||||
|
$callback = $this->callable_or_value;
|
||||||
|
return \method_exists( $callback, '__invoke' )
|
||||||
|
? $callback( $container )
|
||||||
|
: $callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value stored internally for this DependencyType
|
||||||
|
*
|
||||||
|
* @param Container $container The Dependency Injection Container.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
abstract public function get( Container $container );
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Contains the Container class.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Registry;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple Dependency Injection Container
|
||||||
|
*
|
||||||
|
* This is used to manage dependencies used throughout the plugin.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class Container {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of Dependency Type objects used to resolve dependencies.
|
||||||
|
*
|
||||||
|
* @var AbstractDependencyType[]
|
||||||
|
*/
|
||||||
|
private $registry = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public api for adding a factory to the container.
|
||||||
|
*
|
||||||
|
* Factory dependencies will have the instantiation callback invoked
|
||||||
|
* everytime the dependency is requested.
|
||||||
|
*
|
||||||
|
* Typical Usage:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* $container->register( MyClass::class, $container->factory( $mycallback ) );
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param Closure $instantiation_callback This will be invoked when the
|
||||||
|
* dependency is required. It will
|
||||||
|
* receive an instance of this
|
||||||
|
* container so the callback can
|
||||||
|
* retrieve dependencies from the
|
||||||
|
* container.
|
||||||
|
*
|
||||||
|
* @return FactoryType An instance of the FactoryType dependency.
|
||||||
|
*/
|
||||||
|
public function factory( Closure $instantiation_callback ) {
|
||||||
|
return new FactoryType( $instantiation_callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for registering a new dependency with the container.
|
||||||
|
*
|
||||||
|
* By default, the $value will be added as a shared dependency. This means
|
||||||
|
* that it will be a single instance shared among any other classes having
|
||||||
|
* that dependency.
|
||||||
|
*
|
||||||
|
* If you want a new instance everytime it's required, then wrap the value
|
||||||
|
* in a call to the factory method (@see Container::factory for example)
|
||||||
|
*
|
||||||
|
* Note: Currently if the provided id already is registered in the container,
|
||||||
|
* the provided value is ignored.
|
||||||
|
*
|
||||||
|
* @param string $id A unique string identifier for the provided value.
|
||||||
|
* Typically it's the fully qualified name for the
|
||||||
|
* dependency.
|
||||||
|
* @param mixed $value The value for the dependency. Typically, this is a
|
||||||
|
* closure that will create the class instance needed.
|
||||||
|
*/
|
||||||
|
public function register( $id, $value ) {
|
||||||
|
if ( empty( $this->registry[ $id ] ) ) {
|
||||||
|
if ( ! $value instanceof FactoryType ) {
|
||||||
|
$value = new SharedType( $value );
|
||||||
|
}
|
||||||
|
$this->registry[ $id ] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for retrieving the dependency stored in the container for the
|
||||||
|
* given identifier.
|
||||||
|
*
|
||||||
|
* @param string $id The identifier for the dependency being retrieved.
|
||||||
|
* @throws Exception If there is no dependency for the given identifier in
|
||||||
|
* the container.
|
||||||
|
*
|
||||||
|
* @return mixed Typically a class instance.
|
||||||
|
*/
|
||||||
|
public function get( $id ) {
|
||||||
|
if ( ! isset( $this->registry[ $id ] ) ) {
|
||||||
|
// this is a developer facing exception, hence it is not localized.
|
||||||
|
throw new Exception(
|
||||||
|
sprintf(
|
||||||
|
'Cannot construct an instance of %s because it has not been registered.',
|
||||||
|
$id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $this->registry[ $id ]->get( $this );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Holds the FactoryType class
|
||||||
|
*
|
||||||
|
* @package WooCommerce/Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Registry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definition for the FactoryType dependency type.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class FactoryType extends AbstractDependencyType {
|
||||||
|
/**
|
||||||
|
* Invokes and returns the value from the stored internal callback.
|
||||||
|
*
|
||||||
|
* @param Container $container An instance of the dependency injection
|
||||||
|
* container.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function get( Container $container ) {
|
||||||
|
return $this->resolve_value( $container );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Holds the SharedType class definition
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Registry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A definition for the SharedType dependency type.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class SharedType extends AbstractDependencyType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds a cached instance of the value stored (or returned) internally.
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $shared_instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the internal stored and shared value after initial generation.
|
||||||
|
*
|
||||||
|
* @param Container $container An instance of the dependency injection
|
||||||
|
* container.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function get( Container $container ) {
|
||||||
|
if ( empty( $this->shared_instance ) ) {
|
||||||
|
$this->shared_instance = $this->resolve_value( $container );
|
||||||
|
}
|
||||||
|
return $this->shared_instance;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,8 +4,12 @@ global.wp = {};
|
||||||
// wcSettings is required by @woocommerce/* packages
|
// wcSettings is required by @woocommerce/* packages
|
||||||
global.wcSettings = {
|
global.wcSettings = {
|
||||||
adminUrl: 'https://vagrant.local/wp/wp-admin/',
|
adminUrl: 'https://vagrant.local/wp/wp-admin/',
|
||||||
locale: 'en-US',
|
countries: [],
|
||||||
currency: { code: 'USD', precision: 2, symbol: '$' },
|
currency: {
|
||||||
|
code: 'USD',
|
||||||
|
precision: 2,
|
||||||
|
symbol: '$',
|
||||||
|
},
|
||||||
date: {
|
date: {
|
||||||
dow: 0,
|
dow: 0,
|
||||||
},
|
},
|
||||||
|
@ -18,7 +22,8 @@ global.wcSettings = {
|
||||||
refunded: 'Refunded',
|
refunded: 'Refunded',
|
||||||
failed: 'Failed',
|
failed: 'Failed',
|
||||||
},
|
},
|
||||||
l10n: {
|
locale: {
|
||||||
|
siteLocale: 'en_US',
|
||||||
userLocale: 'en_US',
|
userLocale: 'en_US',
|
||||||
weekdaysShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
|
weekdaysShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Tests\Assets;
|
||||||
|
|
||||||
|
use \WP_UnitTestCase;
|
||||||
|
use Automattic\WooCommerce\Blocks\Assets\Api;
|
||||||
|
use Automattic\WooCommerce\Blocks\Tests\Mocks\AssetDataRegistryMock;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the AssetDataRegistry class.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class AssetDataRegistry extends WP_UnitTestCase {
|
||||||
|
private $registry;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
$this->registry = new AssetDataRegistryMock(
|
||||||
|
wc_blocks_container()->get( API::class )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_initial_data() {
|
||||||
|
$this->assertEmpty( $this->registry->get() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_add_data() {
|
||||||
|
$this->registry->add( 'test', 'foo' );
|
||||||
|
$this->assertEquals( [ 'test' => 'foo' ], $this->registry->get() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_add_lazy_data() {
|
||||||
|
$lazy = function () {
|
||||||
|
return 'bar';
|
||||||
|
};
|
||||||
|
$this->registry->add( 'foo', $lazy );
|
||||||
|
// should not be in data yet
|
||||||
|
$this->assertEmpty( $this->registry->get() );
|
||||||
|
$this->registry->execute_lazy_data();
|
||||||
|
// should be in data now
|
||||||
|
$this->assertEquals( [ 'foo' => 'bar' ], $this->registry->get() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_invalid_key_on_adding_data() {
|
||||||
|
$this->expectException( InvalidArgumentException::class );
|
||||||
|
$this->registry->add( [ 'some_value' ], 'foo' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_already_existing_key_on_adding_data() {
|
||||||
|
$this->registry->add( 'foo', 'bar' );
|
||||||
|
$this->expectException( InvalidArgumentException::class );
|
||||||
|
$this->registry->add( 'foo', 'yar' );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Contains Tests for the main file (woocommerce-gutenberg-products-blocks.php)
|
||||||
|
* bootstrap.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Blocks\Tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Tests\Bootstrap;
|
||||||
|
|
||||||
|
use \WP_UnitTestCase;
|
||||||
|
use Automattic\WooCommerce\Blocks\Domain\Bootstrap;
|
||||||
|
use Automattic\WooCommerce\Blocks\Registry\Container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for the bootstrap in the plugin main file
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class MainFile extends WP_UnitTestCase {
|
||||||
|
/**
|
||||||
|
* Holds an instance of the dependency injection container
|
||||||
|
*
|
||||||
|
* @var Container
|
||||||
|
*/
|
||||||
|
private $container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that container is reset between tests.
|
||||||
|
*/
|
||||||
|
public function setUp() {
|
||||||
|
// reset container
|
||||||
|
$this->container = wc_blocks_container( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_wc_blocks_container_returns_same_instance() {
|
||||||
|
$container = wc_blocks_container();
|
||||||
|
$this->assertSame( $container, $this->container );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_wc_blocks_container_reset() {
|
||||||
|
$container = wc_blocks_container( true );
|
||||||
|
$this->assertNotSame( $container, $this->container );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function wc_blocks_bootstrap() {
|
||||||
|
$this->assertInstanceOf( Bootstrap::class, wc_blocks_bootstrap() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Tests\Domain\Package;
|
||||||
|
|
||||||
|
use \WP_UnitTestCase;
|
||||||
|
use Automattic\WooCommerce\Blocks\Domain\Package as TestedPackage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the Package class
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
*/
|
||||||
|
class Package extends WP_UnitTestCase {
|
||||||
|
|
||||||
|
private function get_package() {
|
||||||
|
return new TestedPackage( '1.0.0', __FILE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_get_version() {
|
||||||
|
$this->assertEquals( '1.0.0', $this->get_package()->get_version() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_get_plugin_file() {
|
||||||
|
$this->assertEquals( __FILE__, $this->get_package()->get_plugin_file() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_get_path() {
|
||||||
|
$package = $this->get_package();
|
||||||
|
// test without relative
|
||||||
|
$this->assertEquals( dirname( __FILE__ ) . '/', $package->get_path() );
|
||||||
|
|
||||||
|
//test with relative
|
||||||
|
$expect = dirname( __FILE__ ) . '/build/test';
|
||||||
|
$this->assertEquals( $expect, $package->get_path( 'build/test') );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_get_url() {
|
||||||
|
$package = $this->get_package();
|
||||||
|
$test_url = plugin_dir_url( __FILE__ );
|
||||||
|
// test without relative
|
||||||
|
$this->assertEquals( $test_url, $package->get_url() );
|
||||||
|
|
||||||
|
//test with relative
|
||||||
|
$this->assertEquals(
|
||||||
|
$test_url . 'build/test',
|
||||||
|
$package->get_url( 'build/test' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Tests\Registry;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Registry\Container as ContainerTest;
|
||||||
|
use Automattic\WooCommerce\Blocks\Registry\FactoryType;
|
||||||
|
use Automattic\WooCommerce\Blocks\Tests\Mocks\MockTestDependency;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the Container functionality
|
||||||
|
*
|
||||||
|
* This also implicitly tests the FactoryType and SharedType classes.
|
||||||
|
*
|
||||||
|
* @since $VID:$
|
||||||
|
* @group testing
|
||||||
|
*/
|
||||||
|
class Container extends TestCase {
|
||||||
|
private $container;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
$this->container = new ContainerTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_factory() {
|
||||||
|
$factory = $this->container->factory( function () { return 'foo'; } );
|
||||||
|
$this->assertInstanceOf( FactoryType::class, $factory );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_registering_factory_type() {
|
||||||
|
$this->container->register(
|
||||||
|
MockTestDependency::class,
|
||||||
|
$this->container->factory(
|
||||||
|
function () { return new MockTestDependency; }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$instanceA = $this->container->get( MockTestDependency::class );
|
||||||
|
$instanceB = $this->container->get( MockTestDependency::class );
|
||||||
|
|
||||||
|
// should not be the same instance;
|
||||||
|
$this->assertNotSame( $instanceA, $instanceB );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_registering_shared_type() {
|
||||||
|
$this->container->register(
|
||||||
|
MockTestDependency::class,
|
||||||
|
function () { return new MockTestDependency; }
|
||||||
|
);
|
||||||
|
$instanceA = $this->container->get( MockTestDependency::class );
|
||||||
|
$instanceB = $this->container->get( MockTestDependency::class );
|
||||||
|
|
||||||
|
// should not be the same instance;
|
||||||
|
$this->assertSame( $instanceA, $instanceB );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_registering_shared_type_dependent_on_another_shared_type() {
|
||||||
|
$this->container->register(
|
||||||
|
MockTestDependency::class . 'A',
|
||||||
|
function() { return new MockTestDependency; }
|
||||||
|
);
|
||||||
|
$this->container->register(
|
||||||
|
MockTestDependency::class . 'B',
|
||||||
|
function( $container ) {
|
||||||
|
return new MockTestDependency(
|
||||||
|
$container->get( MockTestDependency::class . 'A' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$instanceA = $this->container->get( MockTestDependency::class . 'A' );
|
||||||
|
$instanceB = $this->container->get( MockTestDependency::class . 'B' );
|
||||||
|
|
||||||
|
// should not be the same instance
|
||||||
|
$this->assertNotSame( $instanceA, $instanceB );
|
||||||
|
|
||||||
|
// dependency on B should be the same as A
|
||||||
|
$this->assertSame( $instanceA, $instanceB->dependency );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Tests\Mocks;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
|
||||||
|
|
||||||
|
class AssetDataRegistryMock extends AssetDataRegistry {
|
||||||
|
|
||||||
|
private $debug = true;
|
||||||
|
|
||||||
|
public function execute_lazy_data() {
|
||||||
|
parent::execute_lazy_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get() {
|
||||||
|
return parent::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set_debug( $debug ) {
|
||||||
|
$this->debug = $debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function debug() {
|
||||||
|
return $this->debug;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Blocks\Tests\Mocks;
|
||||||
|
|
||||||
|
class MockTestDependency {
|
||||||
|
public $dependency;
|
||||||
|
|
||||||
|
public function __construct( $dependency = null ) {
|
||||||
|
$this->dependency = $dependency;
|
||||||
|
}
|
||||||
|
};
|
|
@ -2,6 +2,7 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
const path = require( 'path' );
|
const path = require( 'path' );
|
||||||
|
const { kebabCase } = require( 'lodash' );
|
||||||
const MergeExtractFilesPlugin = require( './bin/merge-extract-files-webpack-plugin' );
|
const MergeExtractFilesPlugin = require( './bin/merge-extract-files-webpack-plugin' );
|
||||||
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
|
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
|
||||||
const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' );
|
const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' );
|
||||||
|
@ -36,10 +37,16 @@ const baseConfig = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const alias = {
|
||||||
|
'@woocommerce/block-settings': path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'assets/js/settings/blocks'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
const requestToExternal = ( request ) => {
|
const requestToExternal = ( request ) => {
|
||||||
const wcDepMap = {
|
const wcDepMap = {
|
||||||
'@woocommerce/settings': [ 'wc', 'wc-shared-settings' ],
|
'@woocommerce/settings': { this: [ 'wc', 'wcSettings' ] },
|
||||||
'@woocommerce/block-settings': [ 'wc', 'wc-block-settings' ],
|
|
||||||
};
|
};
|
||||||
if ( wcDepMap[ request ] ) {
|
if ( wcDepMap[ request ] ) {
|
||||||
return wcDepMap[ request ];
|
return wcDepMap[ request ];
|
||||||
|
@ -48,8 +55,8 @@ const requestToExternal = ( request ) => {
|
||||||
|
|
||||||
const requestToHandle = ( request ) => {
|
const requestToHandle = ( request ) => {
|
||||||
const wcHandleMap = {
|
const wcHandleMap = {
|
||||||
'@woocommerce/settings': 'wc-shared-settings',
|
'@woocommerce/settings': 'wc-settings',
|
||||||
'@woocommerce/block-settings': 'wc-block-settings',
|
'@woocommerce/block-settings': 'wc-settings',
|
||||||
};
|
};
|
||||||
if ( wcHandleMap[ request ] ) {
|
if ( wcHandleMap[ request ] ) {
|
||||||
return wcHandleMap[ request ];
|
return wcHandleMap[ request ];
|
||||||
|
@ -59,11 +66,12 @@ const requestToHandle = ( request ) => {
|
||||||
const CoreConfig = {
|
const CoreConfig = {
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
entry: {
|
entry: {
|
||||||
'wc-shared-settings': './assets/js/settings/shared/index.js',
|
wcSettings: './assets/js/settings/shared/index.js',
|
||||||
'wc-block-settings': './assets/js/settings/blocks/index.js',
|
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
filename: '[name].js',
|
filename: ( chunkData ) => {
|
||||||
|
return `${ kebabCase( chunkData.chunk.name ) }.js`;
|
||||||
|
},
|
||||||
path: path.resolve( __dirname, './build/' ),
|
path: path.resolve( __dirname, './build/' ),
|
||||||
library: [ 'wc', '[name]' ],
|
library: [ 'wc', '[name]' ],
|
||||||
libraryTarget: 'this',
|
libraryTarget: 'this',
|
||||||
|
@ -241,6 +249,7 @@ const GutenbergBlocksConfig = {
|
||||||
requestToHandle,
|
requestToHandle,
|
||||||
} ),
|
} ),
|
||||||
],
|
],
|
||||||
|
resolve: { alias },
|
||||||
};
|
};
|
||||||
|
|
||||||
const BlocksFrontendConfig = {
|
const BlocksFrontendConfig = {
|
||||||
|
@ -326,6 +335,7 @@ const BlocksFrontendConfig = {
|
||||||
requestToHandle,
|
requestToHandle,
|
||||||
} ),
|
} ),
|
||||||
],
|
],
|
||||||
|
resolve: { alias },
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = [ CoreConfig, GutenbergBlocksConfig, BlocksFrontendConfig ];
|
module.exports = [ CoreConfig, GutenbergBlocksConfig, BlocksFrontendConfig ];
|
||||||
|
|
|
@ -68,4 +68,49 @@ if ( is_readable( $autoloader ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_action( 'plugins_loaded', array( '\Automattic\WooCommerce\Blocks\Package', 'init' ) );
|
/**
|
||||||
|
* Loads the dependency injection container for woocommerce blocks.
|
||||||
|
*
|
||||||
|
* @param boolean $reset Used to reset the container to a fresh instance.
|
||||||
|
* Note: this means all dependencies will be reconstructed.
|
||||||
|
*/
|
||||||
|
function wc_blocks_container( $reset = false ) {
|
||||||
|
static $container;
|
||||||
|
if (
|
||||||
|
! $container instanceof Automattic\WooCommerce\Blocks\Registry\Container
|
||||||
|
|| $reset
|
||||||
|
) {
|
||||||
|
$container = new Automattic\WooCommerce\Blocks\Registry\Container();
|
||||||
|
// register Package.
|
||||||
|
$container->register(
|
||||||
|
Automattic\WooCommerce\Blocks\Domain\Package::class,
|
||||||
|
function ( $container ) {
|
||||||
|
return new Automattic\WooCommerce\Blocks\Domain\Package(
|
||||||
|
'2.5.0-dev',
|
||||||
|
__FILE__
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// register Bootstrap.
|
||||||
|
$container->register(
|
||||||
|
Automattic\WooCommerce\Blocks\Domain\Bootstrap::class,
|
||||||
|
function ( $container ) {
|
||||||
|
return new Automattic\WooCommerce\Blocks\Domain\Bootstrap(
|
||||||
|
$container
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $container;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action( 'plugins_loaded', 'wc_blocks_bootstrap' );
|
||||||
|
/**
|
||||||
|
* Boostrap WooCommerce Blocks App
|
||||||
|
*/
|
||||||
|
function wc_blocks_bootstrap() {
|
||||||
|
// initialize bootstrap.
|
||||||
|
wc_blocks_container()->get(
|
||||||
|
Automattic\WooCommerce\Blocks\Domain\Bootstrap::class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue