Skip to content

Commit

Permalink
Merge pull request #127 from happyprime/fix/attribute-deprecation
Browse files Browse the repository at this point in the history
Improve handling of deprecated attributes; allow for replacement via WP-CLI
  • Loading branch information
philcable authored Jan 18, 2024
2 parents 63821ec + d453fa3 commit b2e207d
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 28 deletions.
6 changes: 3 additions & 3 deletions blocks/content-aggregator/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"attributes": {
"customPostType": {
"type": "string",
"default": "post,posts"
"default": "post"
},
"taxonomies": {
"type": "array",
Expand Down Expand Up @@ -89,8 +89,8 @@
"default": ""
},
"customTaxonomy": {
"type": "string",
"default": ""
"type": "array",
"default": []
},
"termID": {
"type": "number",
Expand Down
41 changes: 28 additions & 13 deletions blocks/content-aggregator/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,25 +234,40 @@ export default function ContentAggregatorEdit( props ) {
}
} );

// Handle deprecated taxonomy attributes if needed.
// Handle a case where customPostType has multiple slugs (e.g. document,document).
if (
isStillMounted.currrent &&
( attributes.customTaxonomy || attributes.termID )
attributes.customPostType &&
attributes.customPostType !==
attributes.customPostType.split( ',' )[ 0 ]
) {
const taxonomy = [
{
slug: attributes.customTaxonomy,
terms: [ `${ attributes.termID }` ],
},
];

setAttributes( {
taxonomies: taxonomy,
customTaxonomy: undefined,
termID: undefined,
customPostType: attributes.customPostType.split( ',' )[ 0 ],
} );
}

// Handle deprecated attributes.
if (
isStillMounted.current &&
( attributes.customTaxonomy || attributes.termID )
) {
// If customTaxonomy is an array of data, copy it to the taxonomies attribute.
if (
! taxonomies?.length &&
Array.isArray( attributes.customTaxonomy )
) {
setAttributes( {
taxonomies: attributes.customTaxonomy,
customTaxonomy: undefined,
} );
}

// If taxonomies is already an array and customTaxonomy is set, just remove
// the customTaxonomy attribute.
if ( Array.isArray( taxonomies ) && attributes.customTaxonomy ) {
setAttributes( { customTaxonomy: undefined } );
}
}

return () => {
isStillMounted.current = false;
};
Expand Down
2 changes: 1 addition & 1 deletion build/content-aggregator.asset.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-primitives', 'wp-url'), 'version' => '64a3091040ebcfb8a459');
<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-primitives', 'wp-url'), 'version' => '4875b3dfffe42b9cab2b');
2 changes: 1 addition & 1 deletion build/content-aggregator.js

Large diffs are not rendered by default.

23 changes: 13 additions & 10 deletions includes/block.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,24 @@ function build_query_args( $attributes ) {
}
}

// If this is a previous version of the block, overwrite
// the `customTaxonomy` attribute using the new format.
if ( ! empty( $attributes['termID'] ) && ! empty( $attributes['customTaxonomy'] ) && ! is_array( $attributes['customTaxonomy'] ) ) {
$attributes['customTaxonomy'] = array(
// If this is a previous iteration of the block in which the `customTaxonomy`
// attribute was stored as a string, and the taxonomies attribute is not set,
// create a taxonomies attribute from the data.
if ( empty( $attributes['taxonomies'] ) && ! empty( $attributes['termID'] ) && ! empty( $attributes['customTaxonomy'] ) && ! is_array( $attributes['customTaxonomy'] ) ) {
$attributes['taxonomies'] = array(
array(
'slug' => $attributes['customTaxonomy'],
'terms' => array( $attributes['termID'] ),
),
);
} elseif ( empty( $attributes['taxonomies'] ) && ! empty( $attributes['customTaxonomy'] ) && is_array( $attributes['customTaxonomy'] ) ) {
// If this is a previous iteration of the block in which the `customTaxonomy`
// attribute was stored as an array, and the taxonomies attribute is not set,
// create a taxonomies attribute from the data.
$attributes['taxonomies'] = $attributes['customTaxonomy'];
}

// Use the new `taxonomies` attribute if available.
$taxonomies = ( ! empty( $attributes['taxonomies'] ) )
? $attributes['taxonomies']
: $attributes['customTaxonomy'] ?? array();
$taxonomies = $attributes['taxonomies'];

if ( ! empty( $taxonomies ) ) {
$tax_query = array();
Expand Down Expand Up @@ -167,7 +170,7 @@ function build_query_args( $attributes ) {
*/
function render( $attributes ) {
$defaults = array(
'customPostType' => 'post,posts',
'customPostType' => 'post',
'taxonomies' => array(),
'taxRelation' => '',
'itemCount' => 3,
Expand Down Expand Up @@ -390,7 +393,7 @@ function register_posts_endpoint() {
function posts_rest_response( $request ) {
$attributes = array(
'authors' => $request->get_param( 'authors' ) ?? '',
'customPostType' => $request->get_param( 'post_type' ) ?? 'post,posts',
'customPostType' => $request->get_param( 'post_type' ) ?? 'post',
'taxonomies' => $request->get_param( 'taxonomies' ) ?? array(),
'taxRelation' => $request->get_param( 'tax_relation' ) ?? '',
'itemCount' => $request->get_param( 'per_page' ) ?? 3,
Expand Down
183 changes: 183 additions & 0 deletions includes/cli/class-command.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?php
/**
* Manage and audit content aggregator blocks from the command line.
*
* @package content-aggregator-block
*/

namespace HappyPrime\ContentAggregator\CLI;

use WP_CLI\Utils;
use WP_CLI_Command;

/**
* Commands used to manage and audit content aggregator blocks from the
* command line.
*/
class Command extends WP_CLI_Command {

/**
* Reduce a list of blocks and their inner blocks to a flat
* list of all blocks.
*
* @param array $blocks A list of WordPress blocks.
* @return array A flattened list of WordPress blocks.
*/
private function flatten_blocks( $blocks ): array {
$flattened_blocks = array();

foreach ( $blocks as $block ) {
$flattened_blocks[] = $block;

if ( 0 < count( $block['innerBlocks'] ) ) {
$inner_blocks = $this->flatten_blocks( $block['innerBlocks'] );

$flattened_blocks = array_merge( $flattened_blocks, $inner_blocks );
}
}

return $flattened_blocks;
}

/**
* Retrieve a list of posts containing content aggregator blocks.
*
* @return array A list of post IDs.
*/
private function get_posts(): array {
global $wpdb;

$post_ids = $wpdb->get_results(
"SELECT ID FROM $wpdb->posts WHERE post_content LIKE '%content-aggregator%' AND post_status IN ( 'publish', 'draft', 'pending', 'future' )"
);

return $post_ids ? $post_ids : array();
}

/**
* Retrieve a list of posts containing content aggregator blocks and the
* attributes used for each.
*
* @subcommand audit-blocks
*
* @param array $args The command arguments.
*/
public function audit_blocks( $args ): void {
$format = isset( $args[0] ) ? $args[0] : 'csv';
$post_ids = $this->get_posts();
$results = array();
$progress = Utils\make_progress_bar( 'Auditing content for content aggregator blocks', count( $post_ids ) );

foreach ( $post_ids as $post_id ) {
$post = get_post( $post_id->ID );
$blocks = parse_blocks( $post->post_content );
$blocks = $this->flatten_blocks( $blocks );

foreach ( $blocks as $block ) {
if ( 'happyprime/content-aggregator' !== $block['blockName'] ) {
continue;
}

$attributes = $block['attrs'];

$type = '';
if ( isset( $attributes['customTaxonomy'] ) ) {
$type = is_array( $attributes['customTaxonomy'] ) ? 'array' : 'string';
}

$results[] = array(
'post_id' => $post_id->ID,
'slug' => $post->post_name,
'title' => $post->post_title,
'status' => $post->post_status,
'block' => $block['blockName'],
'customPostType' => isset( $attributes['customPostType'] ) ? $attributes['customPostType'] : '',
'taxonomies' => isset( $attributes['taxonomies'] ) ? wp_json_encode( $attributes['taxonomies'] ) : '',
'customTaxonomy' => isset( $attributes['customTaxonomy'] ) ? wp_json_encode( $attributes['customTaxonomy'] ) : '',
'customType' => $type,
'itemCount' => $attributes['itemCount'] ?? '',
'termID' => isset( $attributes['termID'] ) ? $attributes['termID'] : '',
);
}

$progress->tick();
}

$progress->finish();

$headers = array();
if ( ! empty( $results ) ) {
$headers = array_keys( $results[0] );
}

Utils\format_items( $format, $results, $headers );
}

/**
* Fix incorrect and deprecated attributes on old instances of the content
* aggregator block.
*
* @subcommand fix-block-attributes
*/
public function fix_block_attributes(): void {
$posts = $this->get_posts();
$progress = Utils\make_progress_bar( 'Fixing content aggregator block attributes', count( $posts ) );

foreach ( $posts as $post ) {
$post = get_post( $post->ID );
$blocks = parse_blocks( $post->post_content );
$blocks = $this->flatten_blocks( $blocks );
$content = $post->post_content;

foreach ( $blocks as $block ) {
if ( 'happyprime/content-aggregator' !== $block['blockName'] ) {
continue;
}

$original = serialize_block( $block );
$attributes = $block['attrs'];

// If this is a previous iteration of the block in which the `customTaxonomy`
// attribute was stored as a string, and the taxonomies attribute is not set,
// create a taxonomies attribute from the data.
if ( empty( $attributes['taxonomies'] ) && ! empty( $attributes['termID'] ) && ! empty( $attributes['customTaxonomy'] ) && ! is_array( $attributes['customTaxonomy'] ) ) {
$attributes['taxonomies'] = array(
array(
'slug' => $attributes['customTaxonomy'],
'terms' => array( $attributes['termID'] ),
),
);
unset( $attributes['termID'] );
unset( $attributes['customTaxonomy'] );
} elseif ( empty( $attributes['taxonomies'] ) && ! empty( $attributes['customTaxonomy'] ) && is_array( $attributes['customTaxonomy'] ) ) {
// If this is a previous iteration of the block in which the `customTaxonomy`
// attribute was stored as an array, and the taxonomies attribute is not set,
// create a taxonomies attribute from the data.
$attributes['taxonomies'] = $attributes['customTaxonomy'];
unset( $attributes['customTaxonomy'] );
} elseif ( ! empty( $attributes['taxonomies'] ) && ! empty( $attributes['customTaxonomy'] ) && is_array( $attributes['customTaxonomy'] ) ) {
unset( $attributes['customTaxonomy'] );
}

// If the customPostType attribute is a comma separated string, retrieve the first value.
if ( ! empty( $attributes['customPostType'] ) && is_string( $attributes['customPostType'] ) ) {
$attributes['customPostType'] = explode( ',', $attributes['customPostType'] )[0];
}

$block['attrs'] = $attributes;
$fixed = serialize_block( $block );

$content = str_replace( $original, $fixed, $content );
}

if ( $content !== $post->post_content ) {
$post->post_content = $content;
wp_update_post( $post );
}

$progress->tick();
}

$progress->finish();
}
}
6 changes: 6 additions & 0 deletions plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@
require_once __DIR__ . '/includes/api.php';
require_once __DIR__ . '/includes/block.php';
require_once __DIR__ . '/includes/cache.php';

if ( defined( 'WP_CLI' ) ) {
require_once __DIR__ . '/includes/cli/class-command.php';

\WP_CLI::add_command( 'cab', 'HappyPrime\ContentAggregator\CLI\Command' );
}

0 comments on commit b2e207d

Please sign in to comment.