diff --git a/.changeset/giant-buttons-decide.md b/.changeset/giant-buttons-decide.md
new file mode 100644
index 00000000..c9c7d771
--- /dev/null
+++ b/.changeset/giant-buttons-decide.md
@@ -0,0 +1,5 @@
+---
+"@wpengine/wp-graphql-content-blocks": minor
+---
+
+fix: cleanup constants and refactor autoload handling to improve Composer compatibility.
diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist
index 192f47fe..4cdec649 100644
--- a/.phpcs.xml.dist
+++ b/.phpcs.xml.dist
@@ -40,7 +40,7 @@
Tests for WordPress version compatibility.
https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/wiki/Customizable-sniff-properties
-->
-
+
diff --git a/bin/versionPlugin.js b/bin/versionPlugin.js
index d4055811..451d568e 100644
--- a/bin/versionPlugin.js
+++ b/bin/versionPlugin.js
@@ -68,7 +68,7 @@ async function bumpStableTag(readmeTxt, version) {
async function bumpVersionConstant(pluginFile, version) {
return bumpVersion(
pluginFile,
- /^\s*\$this->define\(\s*'WPGRAPHQL_CONTENT_BLOCKS_VERSION', '([0-9.]+)/gm,
+ /^\s*define\(\s*'WPGRAPHQL_CONTENT_BLOCKS_VERSION', '([0-9.]+)/gm,
version
);
}
diff --git a/includes/Autoloader.php b/includes/Autoloader.php
new file mode 100644
index 00000000..0ba0df03
--- /dev/null
+++ b/includes/Autoloader.php
@@ -0,0 +1,125 @@
+GitHub Releases tab.', 'wp-graphql-content-blocks' );
+
+ if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
+ error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- This is a development notice.
+ sprintf(
+ wp_kses(
+ $error_message,
+ [
+ 'a' => [
+ 'href' => [],
+ 'target' => [],
+ ],
+ ]
+ )
+ )
+ );
+ }
+
+ $hooks = [
+ 'admin_notices',
+ 'network_admin_notices',
+ ];
+
+ foreach ( $hooks as $hook ) {
+ add_action(
+ $hook,
+ static function () use ( $error_message ) {
+
+ // Only show the notice to admins.
+ if ( ! current_user_can( 'manage_options' ) ) {
+ return;
+ }
+
+ ?>
+
+
+ [
+ 'href' => [],
+ 'target' => [],
+ ],
+ ]
+ )
+ )
+ ?>
+
+
+ $args GraphQL query args to pass to the connection resolver.
+ * @param string[] $allowed_block_names The list of allowed block names to filter.
*/
public static function resolve_content_blocks( $node, $args, $allowed_block_names = [] ): array {
/**
@@ -64,57 +63,18 @@ public static function resolve_content_blocks( $node, $args, $allowed_block_name
}
// Parse the blocks from HTML comments to an array of blocks
- $parsed_blocks = parse_blocks( $content );
+ $parsed_blocks = self::parse_blocks( $content );
if ( empty( $parsed_blocks ) ) {
return [];
}
- // 1st Level filtering of blocks that are empty
- $parsed_blocks = array_filter(
- $parsed_blocks,
- static function ( $parsed_block ) {
- if ( ! empty( $parsed_block['blockName'] ) ) {
- return true;
- }
-
- // Strip empty comments and spaces
- $stripped = preg_replace( '//Uis', '', render_block( $parsed_block ) );
- return ! empty( trim( $stripped ?? '' ) );
- },
- ARRAY_FILTER_USE_BOTH
- );
-
- // 2nd Level assigning of unique id's and missing blockNames
- $parsed_blocks = array_map(
- static function ( $parsed_block ) {
- $parsed_block['clientId'] = uniqid();
- // Since Gutenberg assigns an empty blockName for Classic block
- // we define the name here
- if ( empty( $parsed_block['blockName'] ) ) {
- $parsed_block['blockName'] = 'core/freeform';
- }
- return $parsed_block;
- },
- $parsed_blocks
- );
-
- // Resolve reusable blocks - replaces "core/block" with the corresponding block(s) from the reusable ref ID
- TraverseHelpers::traverse_blocks( $parsed_blocks, [ TraverseHelpers::class, 'replace_reusable_blocks' ], 0, PHP_INT_MAX );
// Flatten block list here if requested or if 'flat' value is not selected (default)
if ( ! isset( $args['flat'] ) || 'true' == $args['flat'] ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
$parsed_blocks = self::flatten_block_list( $parsed_blocks );
}
// Final level of filtering out blocks not in the allowed list
- if ( ! empty( $allowed_block_names ) ) {
- $parsed_blocks = array_filter(
- $parsed_blocks,
- static function ( $parsed_block ) use ( $allowed_block_names ) {
- return in_array( $parsed_block['blockName'], $allowed_block_names, true );
- },
- ARRAY_FILTER_USE_BOTH
- );
- }
+ $parsed_blocks = self::filter_allowed_blocks( $parsed_blocks, $allowed_block_names );
/**
* Filters the content blocks after they have been resolved.
@@ -129,6 +89,120 @@ static function ( $parsed_block ) use ( $allowed_block_names ) {
return is_array( $parsed_blocks ) ? $parsed_blocks : [];
}
+ /**
+ * Get blocks from html string.
+ *
+ * @param string $content Content to parse.
+ *
+ * @return array List of blocks.
+ */
+ private static function parse_blocks( $content ): array {
+ $blocks = parse_blocks( $content );
+
+ return self::handle_do_blocks( $blocks );
+ }
+
+ /**
+ * Recursively process blocks.
+ *
+ * This mirrors the `do_blocks` function in WordPress which is responsible for hydrating certain block attributes and supports, but without the forced rendering.
+ *
+ * @param array[] $blocks Blocks data.
+ *
+ * @return array[] The processed blocks.
+ */
+ private static function handle_do_blocks( array $blocks ): array {
+ $parsed = [];
+ foreach ( $blocks as $block ) {
+ $block_data = self::handle_do_block( $block );
+
+ if ( $block_data ) {
+ $parsed[] = $block_data;
+ }
+ }
+
+ // Remove empty blocks.
+ return array_filter( $parsed );
+ }
+
+ /**
+ * Process a block, getting all extra fields.
+ *
+ * @param array $block Block data.
+ *
+ * @return ?array The processed block.
+ */
+ private static function handle_do_block( array $block ): ?array {
+ if ( self::is_block_empty( $block ) ) {
+ return null;
+ }
+
+ // Since Gutenberg assigns an empty blockName for Classic block, we define it here.
+ if ( empty( $block['blockName'] ) ) {
+ $block['blockName'] = 'core/freeform';
+ }
+
+ // Assign a unique clientId to the block.
+ $block['clientId'] = uniqid();
+
+ // @todo apply more hydrations.
+
+ $block = self::populate_reusable_blocks( $block );
+
+ // Prepare innerBlocks.
+ if ( ! empty( $block['innerBlocks'] ) ) {
+ $block['innerBlocks'] = self::handle_do_blocks( $block['innerBlocks'] );
+ }
+
+ return $block;
+ }
+
+ /**
+ * Checks whether a block is really empty, and not just a `core/freeform`.
+ *
+ * @param array $block The block to check.
+ */
+ private static function is_block_empty( array $block ): bool {
+ // If we have a blockName, no need to check further.
+ if ( ! empty( $block['blockName'] ) ) {
+ return false;
+ }
+
+ // @todo add more checks and avoid using render_block().
+
+ // Strip empty comments and spaces
+ $stripped = preg_replace( '//Uis', '', render_block( $block ) );
+
+ return empty( trim( $stripped ?? '' ) );
+ }
+
+ /**
+ * Populates reusable blocks with the blocks from the reusable ref ID.
+ *
+ * @param array $block The block to populate.
+ *
+ * @return array The populated block.
+ */
+ private static function populate_reusable_blocks( array $block ): array {
+ if ( 'core/block' !== $block['blockName'] || ! isset( $block['attrs']['ref'] ) ) {
+ return $block;
+ }
+
+ $reusable_block = get_post( $block['attrs']['ref'] );
+
+ if ( ! $reusable_block ) {
+ return $block;
+ }
+
+ $parsed_blocks = ! empty( $reusable_block->post_content ) ? self::parse_blocks( $reusable_block->post_content ) : null;
+
+ if ( empty( $parsed_blocks ) ) {
+ return $block;
+ }
+
+ return array_merge( ...$parsed_blocks );
+ }
+
/**
* Flattens a list blocks into a single array
*
@@ -145,16 +219,41 @@ private static function flatten_block_list( $blocks ): array {
/**
* Flattens a block and its inner blocks into a single while attaching unique clientId's
*
- * @param mixed $block A block.
+ * @param array $block A parsed block.
*/
private static function flatten_inner_blocks( $block ): array {
- $result = [];
+ $result = [];
+
+ // Assign a unique clientId to the block if it doesn't already have one.
$block['clientId'] = isset( $block['clientId'] ) ? $block['clientId'] : uniqid();
array_push( $result, $block );
+
foreach ( $block['innerBlocks'] as $child ) {
$child['parentClientId'] = $block['clientId'];
- $result = array_merge( $result, self::flatten_inner_blocks( $child ) );
+
+ // Flatten the child, and merge with the result.
+ $result = array_merge( $result, self::flatten_inner_blocks( $child ) );
}
+
return $result;
}
+
+ /**
+ * Filters out disallowed blocks from the list of blocks
+ *
+ * @param array $blocks A list of blocks to filter.
+ * @param string[] $allowed_block_names The list of allowed block names to filter.
+ */
+ private static function filter_allowed_blocks( array $blocks, array $allowed_block_names ): array {
+ if ( empty( $allowed_block_names ) ) {
+ return $blocks;
+ }
+
+ return array_filter(
+ $blocks,
+ static function ( $block ) use ( $allowed_block_names ) {
+ return in_array( $block['blockName'], $allowed_block_names, true );
+ }
+ );
+ }
}
diff --git a/includes/PluginUpdater/UpdateCallbacks.php b/includes/PluginUpdater/UpdateCallbacks.php
index 92cfc4ac..1aed0449 100644
--- a/includes/PluginUpdater/UpdateCallbacks.php
+++ b/includes/PluginUpdater/UpdateCallbacks.php
@@ -36,13 +36,13 @@ function check_for_plugin_updates( $data ) {
}
$response->slug = 'wp-graphql-content-blocks';
- $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_FILE );
+ $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
$meets_wp_req = version_compare( get_bloginfo( 'version' ), $response->requires_at_least, '>=' );
// Only update the response if there's a newer version, otherwise WP shows an update notice for the same version.
if ( $meets_wp_req && version_compare( $current_plugin_data['Version'], $response->version, '<' ) ) {
- $response->plugin = plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_FILE );
- $data->response[ WPGRAPHQL_CONTENT_BLOCKS_PATH ] = $response;
+ $response->plugin = plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
+ $data->response[ WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH ] = $response;
}
return $data;
@@ -60,10 +60,13 @@ function check_for_plugin_updates( $data ) {
* @param string $action The type of information being requested from the Plugin Installation API.
* @param object $args Plugin API arguments.
*
- * @return false|\WPGraphQL\ContentBlocks\PluginUpdater\stdClass $response Plugin API arguments.
+ * @return false|object|array $response Plugin API arguments.
*/
function custom_plugin_api_request( $api, $action, $args ) {
- if ( empty( $args->slug ) || WPGRAPHQL_CONTENT_BLOCKS_SLUG !== $args->slug ) {
+ // Bail if it's not our plugin.
+ $plugin_slug = dirname( plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE ) );
+
+ if ( empty( $args->slug ) || $plugin_slug !== $args->slug ) {
return $api;
}
@@ -96,7 +99,7 @@ function delegate_plugin_row_notice() {
return;
}
- $plugin_basename = plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_FILE );
+ $plugin_basename = plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
remove_action( "after_plugin_row_{$plugin_basename}", 'wp_plugin_update_row' );
add_action( "after_plugin_row_{$plugin_basename}", __NAMESPACE__ . '\display_plugin_row_notice', 10 );
@@ -172,8 +175,9 @@ function display_update_page_notice() {
* @return string
*/
function filter_semver_notice_text( $notice_text, $plugin_filename ) {
- if ( WPGRAPHQL_CONTENT_BLOCKS_PATH !== $plugin_filename ) {
+ if ( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH !== $plugin_filename ) {
return $notice_text;
}
+
return '
' . __( 'THIS UPDATE MAY CONTAIN BREAKING CHANGES: This plugin uses Semantic Versioning, and this new version is a major release. Please review the changelog before updating.', 'wp-graphql-content-blocks' );
}
diff --git a/includes/PluginUpdater/UpdateFunctions.php b/includes/PluginUpdater/UpdateFunctions.php
index 7b736349..3f554182 100644
--- a/includes/PluginUpdater/UpdateFunctions.php
+++ b/includes/PluginUpdater/UpdateFunctions.php
@@ -30,7 +30,7 @@ function get_plugin_data_from_wpe( $args ) {
return $args;
}
- $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_FILE );
+ $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
$meets_wp_req = version_compare( get_bloginfo( 'version' ), $product_info->requires_at_least, '>=' );
$api = new stdClass();
@@ -65,7 +65,7 @@ function get_plugin_api_error() {
* @return \stdClass
*/
function get_remote_plugin_info() {
- $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_FILE );
+ $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
$response = get_transient( 'wpgraphql_content_blocks_product_info' );
if ( false === $response ) {
@@ -101,7 +101,9 @@ function get_remote_plugin_info() {
);
if ( ! property_exists( $response, 'icons' ) || empty( $response->icons['default'] ) ) {
- $response->icons['default'] = WPGRAPHQL_CONTENT_BLOCKS_URL . 'includes/updates/images/wpe-logo-stacked-inverse.svg';
+ $plugin_url = plugin_dir_url( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
+
+ $response->icons['default'] = $plugin_url . 'includes/updates/images/wpe-logo-stacked-inverse.svg';
}
set_transient( 'wpgraphql_content_blocks_product_info', $response, HOUR_IN_SECONDS * 12 );
diff --git a/includes/Utilities/TraverseHelpers.php b/includes/Utilities/TraverseHelpers.php
index 2a4064cc..bc2ed91d 100644
--- a/includes/Utilities/TraverseHelpers.php
+++ b/includes/Utilities/TraverseHelpers.php
@@ -7,21 +7,37 @@
namespace WPGraphQL\ContentBlocks\Utilities;
+use WPGraphQL\ContentBlocks\Data\ContentBlocksResolver;
+
/**
* Class TraverseHelpers
*
* Provides utility functions to traverse and manipulate blocks.
+ *
+ * @deprecated @todo Blocks should be manipulated directly inside ContentBlocksResolver::handle_do_block()
*/
final class TraverseHelpers {
/**
* Traverse blocks and apply a callback with optional depth limit.
*
+ * @deprecated @todo Blocks should be manipulated directly inside ContentBlocksResolver::handle_do_block()
+ *
* @param array &$blocks The blocks to traverse.
* @param callable $callback The callback function to apply to each block.
* @param int $depth The current depth of traversal.
* @param int $max_depth The maximum depth to traverse.
*/
public static function traverse_blocks( &$blocks, $callback, $depth = 0, $max_depth = PHP_INT_MAX ): void {
+ _deprecated_function(
+ __METHOD__,
+ '@todo',
+ sprintf(
+ // translators: %s: class name
+ esc_html__( 'Manipulate blocks directly inside %s::handle_do_block', 'wp-graphql-content-blocks' ),
+ ContentBlocksResolver::class
+ )
+ );
+
foreach ( $blocks as &$block ) {
$callback( $block );
if ( ! empty( $block['innerBlocks'] ) && $depth < $max_depth ) {
@@ -33,9 +49,13 @@ public static function traverse_blocks( &$blocks, $callback, $depth = 0, $max_de
/**
* Example callback function to replace reusable blocks.
*
+ * @deprecated @todo Blocks should be manipulated directly inside ContentBlocksResolver::handle_do_block()
+ *
* @param array $block The block to potentially replace.
*/
public static function replace_reusable_blocks( &$block ): void {
+ _deprecated_function( __METHOD__, '@todo', ContentBlocksResolver::class . '::populate_reusable_blocks' );
+
if ( 'core/block' === $block['blockName'] && isset( $block['attrs']['ref'] ) ) {
$post = get_post( $block['attrs']['ref'] );
$reusable_blocks = ! empty( $post->post_content ) ? parse_blocks( $post->post_content ) : null;
diff --git a/includes/WPGraphQLContentBlocks.php b/includes/WPGraphQLContentBlocks.php
index 25bf5873..febdade1 100644
--- a/includes/WPGraphQLContentBlocks.php
+++ b/includes/WPGraphQLContentBlocks.php
@@ -28,7 +28,9 @@ final class WPGraphQLContentBlocks {
public static function instance() {
if ( ! isset( self::$instance ) || ! ( self::$instance instanceof self ) ) {
self::$instance = new self();
- self::$instance->setup_constants();
+ // @todo Remove this in a major version bump.
+ self::$instance->deprecated_constants();
+
if ( self::$instance->includes() ) {
self::$instance->actions();
}
@@ -64,28 +66,6 @@ public function __wakeup() {
_doing_it_wrong( __FUNCTION__, esc_html__( 'De-serializing instances of the WPGraphQLContentBlocks class is not allowed', 'wp-graphql-content-blocks' ), '0.0.1' );
}
- /**
- * Setup plugin constants.
- *
- * @since 0.0.1
- */
- private function setup_constants(): void {
-
- // Set main file path.
- $main_file_path = dirname( __DIR__ ) . '/wp-graphql.php';
-
- // Plugin version.
- $this->define( 'WPGRAPHQL_CONTENT_BLOCKS_VERSION', '4.1.0' );
- // Plugin Folder Path.
- $this->define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR', plugin_dir_path( $main_file_path ) );
- // Plugin Root File.
- $this->define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE', $main_file_path );
- // Whether to autoload the files or not.
- $this->define( 'WPGRAPHQL_CONTENT_BLOCKS_AUTOLOAD', true );
- // The minimum version of PHP this plugin requires to work properly
- $this->define( 'WPGRAPHQL_CONTENT_BLOCKS_MIN_PHP_VERSION', '7.4' );
- }
-
/**
* Include required files.
* Uses composer's autoload
@@ -93,67 +73,42 @@ private function setup_constants(): void {
* @since 0.0.1
*/
private function includes(): bool {
- /**
- * WPGRAPHQL_CONTENT_BLOCKS_AUTOLOAD can be set to "false" to prevent the autoloader from running.
- * In most cases, this is not something that should be disabled, but some environments
- * may bootstrap their dependencies in a global autoloader that will autoload files
- * before we get to this point, and requiring the autoloader again can trigger fatal errors.
- */
- if ( defined( 'WPGRAPHQL_CONTENT_BLOCKS_AUTOLOAD' ) && true === WPGRAPHQL_CONTENT_BLOCKS_AUTOLOAD ) {
- if ( file_exists( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . 'vendor/autoload.php' ) ) {
- // Autoload Required Classes.
- require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . 'vendor/autoload.php';
- } else {
- add_action(
- 'admin_notices',
- static function () {
- if ( ! current_user_can( 'manage_options' ) ) {
- return;
- }
-
- printf(
- '',
- wp_kses_post(
- __( 'WPGraphQL Content Blocks appears to have been installed without its dependencies. If you meant to download the source code, you can run `composer install` to install dependencies. If you are looking for the production version of the plugin, you can download it from the GitHub Releases tab.', 'wp-graphql-content-blocks' )
- )
- );
- }
- );
- }//end if
-
- // If GraphQL class doesn't exist, then dependencies cannot be
- // detected. This likely means the user cloned the repo from GitHub
- // but did not run `composer install`
- if ( ! class_exists( 'WPGraphQL' ) ) {
- add_action(
- 'admin_notices',
- static function () {
- if ( ! current_user_can( 'manage_options' ) ) {
- return;
- }
-
- printf(
- '',
- esc_html__( 'WPGraphQL Content Blocks will not work without WPGraphQL installed and active.', 'wp-graphql-content-blocks' )
- );
+ // Holds the status of whether the plugin is active or not so we can load the updater functions regardless.
+ $success = true;
+
+ // If GraphQL class doesn't exist, then that plugin is not active.
+ if ( ! class_exists( 'WPGraphQL' ) ) {
+ add_action(
+ 'admin_notices',
+ static function () {
+ if ( ! current_user_can( 'manage_options' ) ) {
+ return;
}
- );
- return false;
- }//end if
- }//end if
+ printf(
+ '',
+ esc_html__( 'WPGraphQL Content Blocks will not work without WPGraphQL installed and active.', 'wp-graphql-content-blocks' )
+ );
+ }
+ );
- require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . 'includes/PluginUpdater/UpdateFunctions.php';
- require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . 'includes/PluginUpdater/UpdateCallbacks.php';
+ $success = false;
+ }
+
+ // Include the updater functions.
+ require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . '/includes/PluginUpdater/UpdateFunctions.php';
+ require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . '/includes/PluginUpdater/UpdateCallbacks.php';
- // phpcs:ignore SlevomatCodingStandard.Variables.UnusedVariable.UnusedVariable -- Library bootstraps itself, hence variable is unused.
- $semver = new \EnforceSemVer\EnforceSemVer( WPGRAPHQL_CONTENT_BLOCKS_PATH );
+ // Bail if the Enforce SemVer class doesn't exist.
+ if ( ! class_exists( 'EnforceSemVer\EnforceSemVer' ) ) {
+ return false;
+ }
- return true;
+ new \EnforceSemVer\EnforceSemVer( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH );
+
+ return $success;
}
/**
@@ -176,16 +131,27 @@ public function init_block_editor_registry( \WPGraphQL\Registry\TypeRegistry $ty
}
/**
- * Define constant if not already set.
- *
- * @param string $name Constant name.
- * @param string|bool $value Constant value.
+ * Sets up deprecated constants.
*
- * @since 1.4.0
+ * @deprecated @todo This can be removed in a major version bump.
*/
- private function define( string $name, $value ): void {
- if ( ! defined( $name ) ) {
- define( $name, $value ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.VariableConstantNameFound
+ private function deprecated_constants(): void {
+ if ( defined( 'WPGRAPHQL_CONTENT_BLOCKS_FILE' ) ) {
+ _doing_it_wrong( 'WPGRAPHQL_CONTENT_BLOCKS_FILE', 'The WPGRAPHQL_CONTENT_BLOCKS_VERSION constant has been deprecated. Use the WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE constant instead.', '@todo' );
+ } else {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_FILE', WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
+ }
+
+ if ( defined( 'WPGRAPHQL_CONTENT_BLOCKS_PATH' ) ) {
+ _doing_it_wrong( 'WPGRAPHQL_CONTENT_BLOCKS_PATH', 'The WPGRAPHQL_CONTENT_BLOCKS_PATH constant has been deprecated. Use the WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH constant instead.', '@todo' );
+ } else {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_PATH', WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH );
+ }
+
+ if ( defined( 'WPGRAPHQL_CONTENT_BLOCKS_MIN_PHP_VERSION' ) ) {
+ _doing_it_wrong( 'WPGRAPHQL_CONTENT_BLOCKS_MIN_PHP_VERSION', 'The WPGRAPHQL_CONTENT_BLOCKS_VERSION constant has been deprecated, with no replacement. It will be removed in a future release.', '@todo' );
+ } else {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_MIN_PHP_VERSION', WPGRAPHQL_CONTENT_BLOCKS_VERSION );
}
}
}
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 62cc5e54..cfa731d0 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -10,17 +10,4 @@ parameters:
count: 1
path: includes/PluginUpdater/UpdateCallbacks.php
- -
- message: "#^Function WPGraphQL\\\\ContentBlocks\\\\PluginUpdater\\\\custom_plugin_api_request\\(\\) has invalid return type WPGraphQL\\\\ContentBlocks\\\\PluginUpdater\\\\stdClass\\.$#"
- count: 1
- path: includes/PluginUpdater/UpdateCallbacks.php
- -
- message: "#^Function WPGraphQL\\\\ContentBlocks\\\\PluginUpdater\\\\custom_plugin_api_request\\(\\) should return WPGraphQL\\\\ContentBlocks\\\\PluginUpdater\\\\stdClass\\|false but returns array\\|object\\|false\\.$#"
- count: 2
- path: includes/PluginUpdater/UpdateCallbacks.php
-
- -
- message: "#^Function WPGraphQL\\\\ContentBlocks\\\\PluginUpdater\\\\custom_plugin_api_request\\(\\) should return WPGraphQL\\\\ContentBlocks\\\\PluginUpdater\\\\stdClass\\|false but returns object\\.$#"
- count: 1
- path: includes/PluginUpdater/UpdateCallbacks.php
diff --git a/phpstan/constants.php b/phpstan/constants.php
index 24df0f25..ab25000d 100644
--- a/phpstan/constants.php
+++ b/phpstan/constants.php
@@ -8,5 +8,4 @@
define( 'WPGRAPHQL_CONTENT_BLOCKS_VERSION', '0.2.1' );
define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE', 'wp-graphql-content-blocks.php' );
define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR', '' );
-define( 'WPGRAPHQL_CONTENT_BLOCKS_MIN_PHP_VERSION', '7.4' );
-define( 'WPGRAPHQL_CONTENT_BLOCKS_PATH', 'wp-graphql-content-blocks.php' );
+define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH', 'wp-graphql-content-blocks.php' );
diff --git a/tests/unit/AutoloaderTest.php b/tests/unit/AutoloaderTest.php
new file mode 100644
index 00000000..47515c3b
--- /dev/null
+++ b/tests/unit/AutoloaderTest.php
@@ -0,0 +1,68 @@
+autoloader = new MockAutoloader();
+ MockAutoloader::reset();
+
+ parent::setUp();
+ }
+
+ public function tearDown(): void {
+ unset( $this->autoloader );
+
+ parent::tearDown();
+ }
+
+ public function testAutoload() {
+ $this->assertTrue( $this->autoloader->autoload() );
+ }
+
+ public function testRequireAutoloader() {
+ $reflection = new \ReflectionClass( $this->autoloader );
+ $is_loaded_property = $reflection->getProperty( 'is_loaded' );
+ $is_loaded_property->setAccessible( true );
+ $is_loaded_property->setValue( $this->autoloader, false );
+
+ $method = $reflection->getMethod( 'require_autoloader' );
+ $method->setAccessible( true );
+
+
+ $this->assertTrue( $method->invokeArgs( $this->autoloader, [ WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . '/vendor/autoload.php' ] ) );
+
+ $is_loaded_property->setValue( $this->autoloader, false );
+ $this->assertFalse( $method->invokeArgs( $this->autoloader, [ '/path/to/invalid/autoload.php' ] ) );
+
+ // Capture the admin notice output
+
+ $admin_id = $this->factory->user->create( [ 'role' => 'administrator' ] );
+
+ wp_set_current_user( $admin_id );
+
+ set_current_screen( 'dashboard' );
+ ob_start();
+ do_action( 'admin_notices' );
+
+ $output = ob_get_clean();
+ $this->assertStringContainsString( 'WPGraphQL Content Blocks appears to have been installed without its dependencies.', $output );
+
+ // Cleanup
+ wp_delete_user( $admin_id );
+ remove_all_actions( 'admin_notices' );
+ }
+}
diff --git a/tests/unit/TraverseHelpersTest.php b/tests/unit/TraverseHelpersTest.php
deleted file mode 100644
index 7b9589fc..00000000
--- a/tests/unit/TraverseHelpersTest.php
+++ /dev/null
@@ -1,89 +0,0 @@
-post_id = wp_insert_post(
- [
- 'post_title' => 'Post Title',
- 'post_content' => preg_replace(
- '/\s+/',
- ' ',
- trim(
- '
-
- Test
-
- '
- )
- ),
- 'post_status' => 'publish',
- ]
- );
- }
-
- public function tearDown(): void {
- // your tear down methods here
- parent::tearDown();
-
- wp_delete_post( $this->post_id, true );
- }
-
- public function testTraverseBlocks() {
- // Sample blocks data
- $blocks = [
- [
- 'blockName' => 'core/group',
- 'attrs' => [],
- 'innerBlocks' => [
- [
- 'blockName' => 'core/block',
- 'attrs' => [ 'ref' => $this->post_id ],
- 'innerBlocks' => [],
- ],
- ],
- ],
- [
- 'blockName' => 'core/block',
- 'attrs' => [ 'ref' => $this->post_id ],
- 'innerBlocks' => [],
- ],
- ];
-
- // Expected result after replacing reusable blocks
- $expected = [
- [
- 'blockName' => 'core/group',
- 'attrs' => [],
- 'innerBlocks' => [
- [
- 'blockName' => 'core/paragraph',
- 'attrs' => [],
- 'innerBlocks' => [],
- 'innerHTML' => ' Test
',
- 'innerContent' => [ 0 => ' Test
' ],
- ],
- ],
- ],
- [
- 'blockName' => 'core/paragraph',
- 'attrs' => [],
- 'innerBlocks' => [],
- 'innerHTML' => ' Test
',
- 'innerContent' => [ 0 => ' Test
' ],
- ],
- ];
-
- TraverseHelpers::traverse_blocks( $blocks, [ TraverseHelpers::class, 'replace_reusable_blocks' ], 0, PHP_INT_MAX );
- $this->assertEquals( $expected, $blocks );
- }
-}
diff --git a/tests/unit/WPGraphQLContentBlocksTest.php b/tests/unit/WPGraphQLContentBlocksTest.php
index fad91b7a..7421305e 100644
--- a/tests/unit/WPGraphQLContentBlocksTest.php
+++ b/tests/unit/WPGraphQLContentBlocksTest.php
@@ -36,15 +36,4 @@ public function testCloneWPGraphQL() {
$this->assertTrue( $rc->hasMethod( '__clone' ) );
$this->assertTrue( $rc->hasMethod( '__wakeup' ) );
}
-
- /**
- * @covers WPGraphQLContentBlocks::setup_constants()
- */
- public function testSetupConstants() {
- $this->assertTrue( defined( 'WPGRAPHQL_CONTENT_BLOCKS_VERSION' ) );
- $this->assertTrue( defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR' ) );
- $this->assertTrue( defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE' ) );
- $this->assertTrue( defined( 'WPGRAPHQL_CONTENT_BLOCKS_AUTOLOAD' ) );
- $this->assertTrue( defined( 'WPGRAPHQL_CONTENT_BLOCKS_MIN_PHP_VERSION' ) );
- }
}
diff --git a/wp-graphql-content-blocks.php b/wp-graphql-content-blocks.php
index c8fa64fd..00089f6d 100644
--- a/wp-graphql-content-blocks.php
+++ b/wp-graphql-content-blocks.php
@@ -19,14 +19,33 @@
exit;
}
-define( 'WPGRAPHQL_CONTENT_BLOCKS_DIR', __DIR__ );
-define( 'WPGRAPHQL_CONTENT_BLOCKS_FILE', __FILE__ );
-define( 'WPGRAPHQL_CONTENT_BLOCKS_URL', plugin_dir_url( __FILE__ ) );
-define( 'WPGRAPHQL_CONTENT_BLOCKS_PATH', plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_FILE ) );
-define( 'WPGRAPHQL_CONTENT_BLOCKS_SLUG', dirname( plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_FILE ) ) );
-
-if ( ! class_exists( 'WPGraphQLContentBlocks' ) ) {
- require_once __DIR__ . '/includes/WPGraphQLContentBlocks.php';
+if ( ! function_exists( 'wpgraphql_content_blocks_constants' ) ) {
+ /**
+ * Defines plugin constants.
+ *
+ * @since @todo
+ */
+ function wpgraphql_content_blocks_constants(): void {
+ // Whether to autoload the files or not.
+ if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_AUTOLOAD' ) ) {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_AUTOLOAD', true );
+ }
+
+ if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR' ) ) {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR', __DIR__ );
+ }
+
+ if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE' ) ) {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE', __FILE__ );
+ }
+
+ if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH' ) ) {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH', plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE ) );
+ }
+ if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_VERSION' ) ) {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_VERSION', '4.1.0' );
+ }
+ }
}
@@ -37,6 +56,15 @@
* @since 0.0.1
*/
function wpgraphql_content_blocks_init(): void {
+ // Define plugin constants.
+ wpgraphql_content_blocks_constants();
+
+ // Load the autoloader.
+ require_once __DIR__ . '/includes/Autoloader.php';
+ if ( ! \WPGraphQL\ContentBlocks\Autoloader::autoload() ) {
+ return;
+ }
+
// Instantiate the plugin class.
WPGraphQLContentBlocks::instance();
}