assets
3 years ago
build
3 years ago
images
4 years ago
packages
3 years ago
patches
4 years ago
patterns
3 years ago
src
3 months ago
templates
3 years ago
vendor
3 years ago
LICENSE
5 years ago
global.d.ts
4 years ago
readme.txt
3 years ago
woocommerce-gutenberg-products-block.php
3 years ago
woocommerce-gutenberg-products-block.php
278 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Plugin Name: WooCommerce Blocks |
| 4 | * Plugin URI: https://github.com/woocommerce/woocommerce-gutenberg-products-block |
| 5 | * Description: WooCommerce blocks for the Gutenberg editor. |
| 6 | * Version: 8.3.3 |
| 7 | * Author: Automattic |
| 8 | * Author URI: https://woocommerce.com |
| 9 | * Text Domain: woo-gutenberg-products-block |
| 10 | * Requires at least: 6.0 |
| 11 | * Requires PHP: 7.0 |
| 12 | * WC requires at least: 6.7 |
| 13 | * WC tested up to: 6.8 |
| 14 | * |
| 15 | * @package WooCommerce\Blocks |
| 16 | * @internal This file is only used when running as a feature plugin. |
| 17 | */ |
| 18 | |
| 19 | defined( 'ABSPATH' ) || exit; |
| 20 | |
| 21 | $minimum_wp_version = '6.0'; |
| 22 | |
| 23 | if ( ! defined( 'WC_BLOCKS_IS_FEATURE_PLUGIN' ) ) { |
| 24 | define( 'WC_BLOCKS_IS_FEATURE_PLUGIN', true ); |
| 25 | } |
| 26 | /** |
| 27 | * Whether notices must be displayed in the current page (plugins and WooCommerce pages). |
| 28 | * |
| 29 | * @since 2.5.0 |
| 30 | */ |
| 31 | function should_display_compatibility_notices() { |
| 32 | $current_screen = get_current_screen(); |
| 33 | |
| 34 | if ( ! isset( $current_screen ) ) { |
| 35 | return false; |
| 36 | } |
| 37 | |
| 38 | $is_plugins_page = |
| 39 | property_exists( $current_screen, 'id' ) && |
| 40 | 'plugins' === $current_screen->id; |
| 41 | $is_woocommerce_page = |
| 42 | property_exists( $current_screen, 'parent_base' ) && |
| 43 | 'woocommerce' === $current_screen->parent_base; |
| 44 | |
| 45 | return $is_plugins_page || $is_woocommerce_page; |
| 46 | } |
| 47 | |
| 48 | if ( version_compare( $GLOBALS['wp_version'], $minimum_wp_version, '<' ) ) { |
| 49 | /** |
| 50 | * Outputs for an admin notice about running WooCommerce Blocks on outdated WordPress. |
| 51 | * |
| 52 | * @since 2.5.0 |
| 53 | */ |
| 54 | function woocommerce_blocks_admin_unsupported_wp_notice() { |
| 55 | if ( should_display_compatibility_notices() ) { |
| 56 | ?> |
| 57 | <div class="notice notice-error"> |
| 58 | <p><?php esc_html_e( 'The WooCommerce Blocks feature plugin requires a more recent version of WordPress and has been paused. Please update WordPress to continue enjoying WooCommerce Blocks.', 'woocommerce' ); ?></p> |
| 59 | </div> |
| 60 | <?php |
| 61 | } |
| 62 | } |
| 63 | add_action( 'admin_notices', 'woocommerce_blocks_admin_unsupported_wp_notice' ); |
| 64 | return; |
| 65 | } |
| 66 | |
| 67 | /** |
| 68 | * Returns whether the current version is a development version |
| 69 | * Note this relies on composer.json version, not plugin version. |
| 70 | * Development installs of the plugin don't have a version defined in |
| 71 | * composer json. |
| 72 | * |
| 73 | * @return bool True means the current version is a development version. |
| 74 | */ |
| 75 | function woocommerce_blocks_is_development_version() { |
| 76 | $composer_file = __DIR__ . '/composer.json'; |
| 77 | if ( ! is_readable( $composer_file ) ) { |
| 78 | return false; |
| 79 | } |
| 80 | // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- including local file |
| 81 | $composer_config = json_decode( file_get_contents( $composer_file ), true ); |
| 82 | return ! isset( $composer_config['version'] ); |
| 83 | } |
| 84 | |
| 85 | /** |
| 86 | * If development version is detected and the Jetpack constant is not defined, show a notice. |
| 87 | */ |
| 88 | if ( woocommerce_blocks_is_development_version() && ! defined( 'JETPACK_AUTOLOAD_DEV' ) ) { |
| 89 | add_action( |
| 90 | 'admin_notices', |
| 91 | function() { |
| 92 | echo '<div class="error"><p>'; |
| 93 | printf( |
| 94 | /* translators: %1$s is referring to a php constant name, %2$s is referring to the wp-config.php file. */ |
| 95 | esc_html__( 'WooCommerce Blocks development mode requires the %1$s constant to be defined and true in your %2$s file. Otherwise you are loading the blocks package from WooCommerce core.', 'woocommerce' ), |
| 96 | 'JETPACK_AUTOLOAD_DEV', |
| 97 | 'wp-config.php' |
| 98 | ); |
| 99 | echo '</p></div>'; |
| 100 | } |
| 101 | ); |
| 102 | } |
| 103 | |
| 104 | |
| 105 | /** |
| 106 | * Autoload packages. |
| 107 | * |
| 108 | * The package autoloader includes version information which prevents classes in this feature plugin |
| 109 | * conflicting with WooCommerce core. |
| 110 | * |
| 111 | * We want to fail gracefully if `composer install` has not been executed yet, so we are checking for the autoloader. |
| 112 | * If the autoloader is not present, let's log the failure and display a nice admin notice. |
| 113 | */ |
| 114 | $autoloader = __DIR__ . '/vendor/autoload_packages.php'; |
| 115 | if ( is_readable( $autoloader ) ) { |
| 116 | require $autoloader; |
| 117 | } else { |
| 118 | if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
| 119 | error_log( // phpcs:ignore |
| 120 | sprintf( |
| 121 | /* translators: 1: composer command. 2: plugin directory */ |
| 122 | esc_html__( 'Your installation of the WooCommerce Blocks feature plugin is incomplete. Please run %1$s within the %2$s directory.', 'woocommerce' ), |
| 123 | '`composer install`', |
| 124 | '`' . esc_html( str_replace( ABSPATH, '', __DIR__ ) ) . '`' |
| 125 | ) |
| 126 | ); |
| 127 | } |
| 128 | /** |
| 129 | * Outputs an admin notice if composer install has not been ran. |
| 130 | */ |
| 131 | add_action( |
| 132 | 'admin_notices', |
| 133 | function() { |
| 134 | ?> |
| 135 | <div class="notice notice-error"> |
| 136 | <p> |
| 137 | <?php |
| 138 | printf( |
| 139 | /* translators: 1: composer command. 2: plugin directory */ |
| 140 | esc_html__( 'Your installation of the WooCommerce Blocks feature plugin is incomplete. Please run %1$s within the %2$s directory.', 'woocommerce' ), |
| 141 | '<code>composer install</code>', |
| 142 | '<code>' . esc_html( str_replace( ABSPATH, '', __DIR__ ) ) . '</code>' |
| 143 | ); |
| 144 | ?> |
| 145 | </p> |
| 146 | </div> |
| 147 | <?php |
| 148 | } |
| 149 | ); |
| 150 | return; |
| 151 | } |
| 152 | |
| 153 | add_action( 'plugins_loaded', array( '\Automattic\WooCommerce\Blocks\Package', 'init' ) ); |
| 154 | |
| 155 | /** |
| 156 | * WordPress will look for translation in the following order: |
| 157 | * - wp-content/plugins/woocommerce-blocks/languages/woo-gutenberg-products-block-{locale}-{handle}.json |
| 158 | * - wp-content/plugins/woocommerce-blocks/languages/woo-gutenberg-products-block-{locale}-{md5-handle}.json |
| 159 | * - wp-content/languages/plugins/woo-gutenberg-products-block-{locale}-{md5-handle}.json |
| 160 | * |
| 161 | * We check if the last one exists, and if it doesn't we try to load the |
| 162 | * corresponding JSON file from the WC Core. |
| 163 | * |
| 164 | * @param string|false $file Path to the translation file to load. False if there isn't one. |
| 165 | * @param string $handle Name of the script to register a translation domain to. |
| 166 | * @param string $domain The text domain. |
| 167 | * |
| 168 | * @return string|false Path to the translation file to load. False if there isn't one. |
| 169 | */ |
| 170 | function load_woocommerce_core_json_translation( $file, $handle, $domain ) { |
| 171 | if ( 'woo-gutenberg-products-block' !== $domain ) { |
| 172 | return $file; |
| 173 | } |
| 174 | |
| 175 | $lang_dir = WP_LANG_DIR . '/plugins'; |
| 176 | |
| 177 | /** |
| 178 | * We only care about the translation file of the feature plugin in the |
| 179 | * wp-content/languages folder. |
| 180 | */ |
| 181 | if ( false === strpos( $file, $lang_dir ) ) { |
| 182 | return $file; |
| 183 | } |
| 184 | |
| 185 | // If the translation file for feature plugin exist, use it. |
| 186 | if ( is_readable( $file ) ) { |
| 187 | return $file; |
| 188 | } |
| 189 | |
| 190 | global $wp_scripts; |
| 191 | |
| 192 | if ( ! isset( $wp_scripts->registered[ $handle ], $wp_scripts->registered[ $handle ]->src ) ) { |
| 193 | return $file; |
| 194 | } |
| 195 | |
| 196 | $handle_src = explode( '/build/', $wp_scripts->registered[ $handle ]->src ); |
| 197 | $handle_filename = $handle_src[1]; |
| 198 | $locale = determine_locale(); |
| 199 | $lang_dir = WP_LANG_DIR . '/plugins'; |
| 200 | |
| 201 | // Translations are always based on the unminified filename. |
| 202 | if ( substr( $handle_filename, -7 ) === '.min.js' ) { |
| 203 | $handle_filename = substr( $handle_filename, 0, -7 ) . '.js'; |
| 204 | } |
| 205 | |
| 206 | $core_path_md5 = md5( 'packages/woocommerce-blocks/build/' . $handle_filename ); |
| 207 | |
| 208 | /** |
| 209 | * Return file path of the corresponding translation file in the WC Core is |
| 210 | * enough because `load_script_translations()` will check for its existence |
| 211 | * before loading it. |
| 212 | */ |
| 213 | return $lang_dir . '/woocommerce-' . $locale . '-' . $core_path_md5 . '.json'; |
| 214 | } |
| 215 | |
| 216 | add_filter( 'load_script_translation_file', 'load_woocommerce_core_json_translation', 10, 3 ); |
| 217 | |
| 218 | /** |
| 219 | * Filter translations so we can retrieve translations from Core when the original and the translated |
| 220 | * texts are the same (which happens when translations are missing). |
| 221 | * |
| 222 | * @param string $translation Translated text based on WC Blocks translations. |
| 223 | * @param string $text Text to translate. |
| 224 | * @param string $domain The text domain. |
| 225 | * @return string WC Blocks translation. In case it's the same as $text, Core translation. |
| 226 | */ |
| 227 | function woocommerce_blocks_get_php_translation_from_core( $translation, $text, $domain ) { |
| 228 | if ( 'woo-gutenberg-products-block' !== $domain ) { |
| 229 | return $translation; |
| 230 | } |
| 231 | |
| 232 | // When translation is the same, that could mean the string is not translated. |
| 233 | // In that case, load it from core. |
| 234 | if ( $translation === $text ) { |
| 235 | return translate( $text, 'woocommerce' ); // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction, WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.TextDomainMismatch |
| 236 | } |
| 237 | return $translation; |
| 238 | } |
| 239 | |
| 240 | add_filter( 'gettext', 'woocommerce_blocks_get_php_translation_from_core', 10, 3 ); |
| 241 | |
| 242 | /** |
| 243 | * Add notice to the admin dashboard if the plugin is outdated. |
| 244 | * |
| 245 | * @see https://github.com/woocommerce/woocommerce-blocks/issues/5587 |
| 246 | */ |
| 247 | function woocommerce_blocks_plugin_outdated_notice() { |
| 248 | $is_active = |
| 249 | is_plugin_active( 'woo-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) || |
| 250 | is_plugin_active( 'woocommerce-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) || |
| 251 | is_plugin_active( 'woocommerce-blocks/woocommerce-gutenberg-products-block.php' ); |
| 252 | |
| 253 | if ( ! $is_active ) { |
| 254 | return; |
| 255 | } |
| 256 | |
| 257 | $woocommerce_blocks_path = \Automattic\WooCommerce\Blocks\Package::get_path(); |
| 258 | |
| 259 | /** |
| 260 | * Check the current WC Blocks path. If the WC Blocks plugin is active but |
| 261 | * the current path is from the WC Core, we can consider the plugin is |
| 262 | * outdated because Jetpack Autoloader always loads the newer package. |
| 263 | */ |
| 264 | if ( ! strpos( $woocommerce_blocks_path, 'packages/woocommerce-blocks' ) ) { |
| 265 | return; |
| 266 | } |
| 267 | |
| 268 | if ( should_display_compatibility_notices() ) { |
| 269 | ?> |
| 270 | <div class="notice notice-warning"> |
| 271 | <p><?php esc_html_e( 'You have WooCommerce Blocks installed, but the WooCommerce bundled version is running because it is more up-to-date. This may cause unexpected compatibility issues. Please update the WooCommerce Blocks plugin.', 'woocommerce' ); ?></p> |
| 272 | </div> |
| 273 | <?php |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | add_action( 'admin_notices', 'woocommerce_blocks_plugin_outdated_notice' ); |
| 278 |