Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions dynamic-shapes/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org

# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab

[*.{yml,yaml}]
indent_style = space
indent_size = 2
30 changes: 30 additions & 0 deletions dynamic-shapes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Coverage directory used by tools like istanbul
coverage

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Output of `npm pack`
*.tgz

# Output of `wp-scripts plugin-zip`
*.zip

# dotenv environment variables file
.env
80 changes: 80 additions & 0 deletions dynamic-shapes/classes/class-wpcomsp-blocks-self-update.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php
/**
* Plugin Autoupdate Filter Self Update class.
* sets up autoupdates for this GitHub-hosted plugin.
*
* @package wpcomsp
*/

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class WPCOMSP_Blocks_Self_Update {

public static $instance;

/**
* Get instance of this class.
*
* @return WPCOMSP_Blocks_Self_Update
*/
public static function get_instance() {
if ( ! self::$instance ) {
self::$instance = new self();
}

return self::$instance;
}

/**
* Initialize WordPress hooks
*/
public function hooks() {
add_filter( 'update_plugins_opsoasis.wpspecialprojects.com', array( $this, 'self_update' ), 10, 3 );
}

/**
* Check for updates to this plugin
*
* @param array $update Array of update data.
* @param array $plugin_data Array of plugin data.
* @param string $plugin_file Path to plugin file.
*
* @return array|bool Array of update data or false if no update available.
*/
public function self_update( $update, array $plugin_data, string $plugin_file ) {
// Already completed update check elsewhere.
if ( ! empty( $update ) ) {
return $update;
}

$plugin_filename_parts = explode( '/', $plugin_file );

// Ask opsoasis.mystagingwebsite.com if there's an update.
$response = wp_remote_get(
'https://opsoasis.wpspecialprojects.com/wp-json/opsoasis-blocks-version-manager/v1/update-check',
array(
'body' => array(
'plugin' => $plugin_filename_parts[0],
'version' => $plugin_data['Version'],
),
)
);

// Bail if this plugin wasn't found on opsoasis.mystagingwebsite.com.
if ( 404 === wp_remote_retrieve_response_code( $response ) || 202 === wp_remote_retrieve_response_code( $response ) ) {
return $update;
}

$updated_version = wp_remote_retrieve_body( $response );
$updated_array = json_decode( $updated_version, true );

return array(
'slug' => $updated_array['slug'],
'version' => $updated_array['version'],
'url' => $updated_array['package_url'],
'package' => $updated_array['package_url'],
);
Comment on lines +52 to +78
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Harden the self-update response handling.

If wp_remote_get() returns a WP_Error, a non-JSON body, or a payload missing the expected keys, line 74 tries to read array offsets on null, which triggers a fatal error during the update check. Guard the remote call and decode before dereferencing.

-		$response = wp_remote_get(
+		$response = wp_remote_get(
 			'https://opsoasis.wpspecialprojects.com/wp-json/opsoasis-blocks-version-manager/v1/update-check',
 			array(
 				'body' => array(
 					'plugin'  => $plugin_filename_parts[0],
 					'version' => $plugin_data['Version'],
 				),
 			)
 		);
 
-		if ( 404 === wp_remote_retrieve_response_code( $response ) || 202 === wp_remote_retrieve_response_code( $response ) ) {
+		if ( is_wp_error( $response ) ) {
+			return $update;
+		}
+
+		$response_code = wp_remote_retrieve_response_code( $response );
+
+		if ( 404 === $response_code || 202 === $response_code ) {
 			return $update;
 		}
 
 		$updated_version = wp_remote_retrieve_body( $response );
-		$updated_array   = json_decode( $updated_version, true );
+		$updated_array   = json_decode( $updated_version, true );
+
+		if ( ! is_array( $updated_array ) || empty( $updated_array['slug'] ) || empty( $updated_array['version'] ) || empty( $updated_array['package_url'] ) ) {
+			return $update;
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$plugin_filename_parts = explode( '/', $plugin_file );
// Ask opsoasis.mystagingwebsite.com if there's an update.
$response = wp_remote_get(
'https://opsoasis.wpspecialprojects.com/wp-json/opsoasis-blocks-version-manager/v1/update-check',
array(
'body' => array(
'plugin' => $plugin_filename_parts[0],
'version' => $plugin_data['Version'],
),
)
);
// Bail if this plugin wasn't found on opsoasis.mystagingwebsite.com.
if ( 404 === wp_remote_retrieve_response_code( $response ) || 202 === wp_remote_retrieve_response_code( $response ) ) {
return $update;
}
$updated_version = wp_remote_retrieve_body( $response );
$updated_array = json_decode( $updated_version, true );
return array(
'slug' => $updated_array['slug'],
'version' => $updated_array['version'],
'url' => $updated_array['package_url'],
'package' => $updated_array['package_url'],
);
$plugin_filename_parts = explode( '/', $plugin_file );
// Ask opsoasis.mystagingwebsite.com if there's an update.
$response = wp_remote_get(
'https://opsoasis.wpspecialprojects.com/wp-json/opsoasis-blocks-version-manager/v1/update-check',
array(
'body' => array(
'plugin' => $plugin_filename_parts[0],
'version' => $plugin_data['Version'],
),
)
);
if ( is_wp_error( $response ) ) {
return $update;
}
$response_code = wp_remote_retrieve_response_code( $response );
// Bail if this plugin wasn't found on opsoasis.mystagingwebsite.com.
if ( 404 === $response_code || 202 === $response_code ) {
return $update;
}
$updated_version = wp_remote_retrieve_body( $response );
$updated_array = json_decode( $updated_version, true );
if ( ! is_array( $updated_array ) || empty( $updated_array['slug'] ) || empty( $updated_array['version'] ) || empty( $updated_array['package_url'] ) ) {
return $update;
}
return array(
'slug' => $updated_array['slug'],
'version' => $updated_array['version'],
'url' => $updated_array['package_url'],
'package' => $updated_array['package_url'],
);
🤖 Prompt for AI Agents
In dynamic-shapes/classes/class-wpcomsp-blocks-self-update.php around lines 52
to 78, the code assumes wp_remote_get() succeeded and json_decode() returned an
array; this can cause fatal errors when wp_remote_get() returns a WP_Error, a
non-200/OK response, an invalid JSON body, or when expected keys are missing.
Fix: after wp_remote_get() check is_wp_error($response) and return $update on
error; verify wp_remote_retrieve_response_code($response) === 200 before
proceeding; get the body, json_decode it and confirm the result is an array;
ensure keys 'slug','version','package_url' exist (use isset or array_key_exists)
before building the return array; if any check fails, return the original
$update (optionally log the error).

}
}
50 changes: 50 additions & 0 deletions dynamic-shapes/dynamic-shapes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* Plugin Name: Dynamic Shapes
* Description: Extends the core Group, Image, and Featured Image blocks with controls for adjusting corners to create unique shapes.
* Version: 0.1.0
* Requires at least: 6.7
* Requires PHP: 7.4
* Author: Automattic Special Projects
* Author URI: https://wpspecialprojects.wordpress.com/
* Update URI: https://opsoasis.wpspecialprojects.com/dynamic-shapes/
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: wpcomsp-dynamic-shapes
*
* @package wpcomsp-dynamic-shapes
*/

defined( 'ABSPATH' ) || exit;

define( 'WPCOMSP_DYNAMIC_SHAPES_DIR', plugin_dir_path( __FILE__ ) );
define( 'WPCOMSP_DYNAMIC_SHAPES_URL', plugin_dir_url( __FILE__ ) );

// Add the self update class if needed.
if ( ! class_exists( 'WPCOMSP_Blocks_Self_Update' ) ) {
require __DIR__ . '/classes/class-wpcomsp-blocks-self-update.php';

$wpcomsp_blocks_self_update = WPCOMSP_Blocks_Self_Update::get_instance();
$wpcomsp_blocks_self_update->hooks();
}

/**
* Setup auto-updates from the monorepo.
*
* @param array $blocks Array of plugin files.
*
* @return array
*/
add_filter(
'wpcomsp_installed_blocks',
function ( $blocks ) {
$blocks[] = 'dynamic-shapes';

return $blocks;
}
);

// Autoload all files in the includes directory.
foreach ( glob( __DIR__ . '/includes/*.php' ) as $wpcomsp_dynamic_shapes_filename ) {
include $wpcomsp_dynamic_shapes_filename;
}
Loading