Skip to content

Commit

Permalink
tmp: stash changes
Browse files Browse the repository at this point in the history
  • Loading branch information
DDEV User committed Sep 29, 2024
1 parent 60d9f13 commit bddd798
Show file tree
Hide file tree
Showing 10 changed files with 248 additions and 102 deletions.
23 changes: 12 additions & 11 deletions includes/Blocks/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace WPGraphQL\ContentBlocks\Blocks;

use WPGraphQL\ContentBlocks\Data\BlockAttributeResolver;
use \WPGraphQL\ContentBlocks\Model\Block as BlockModel;
use WPGraphQL\ContentBlocks\Registry\Registry;
use WPGraphQL\ContentBlocks\Type\Scalar\Scalar;
use WPGraphQL\ContentBlocks\Utilities\WPGraphQLHelpers;
Expand Down Expand Up @@ -108,6 +109,7 @@ private function register_block_attributes_as_fields(): void {
'fields' => $block_attribute_fields,
]
);

register_graphql_field(
$this->type_name,
'attributes',
Expand Down Expand Up @@ -219,8 +221,9 @@ private function get_block_attribute_fields( ?array $block_attributes, string $p
$config = [
$attribute_name => $attribute_config,
];
$result = $this->resolve_block_attributes_recursive( $block['attrs'], wp_unslash( render_block( $block ) ), $config );
$result = $this->resolve_block_attributes_recursive( $block, $config );

// Normalize the value.
return $result[ $attribute_name ];
},
];
Expand Down Expand Up @@ -325,7 +328,9 @@ private function normalize_attribute_value( $value, $type ) {
}

/**
* Register the Type for the block. This happens after all other object types are already registered.
* Register the Type for the block.
*
* This happens after all other object types are already registered.
*/
private function register_type(): void {
register_graphql_object_type(
Expand All @@ -338,9 +343,6 @@ private function register_type(): void {
'name' => [
'type' => 'String',
'description' => __( 'The name of the block', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return isset( $block['blockName'] ) ? (string) $block['blockName'] : null;
},
],
],
]
Expand Down Expand Up @@ -368,18 +370,17 @@ private function get_block_attributes_interfaces(): array {
/**
* Resolved the value of the block attributes based on the specified config
*
* @param array<string,mixed> $attribute_values The block current attributes value.
* @param string $html The block rendered html.
* @param array<string,mixed> $attribute_configs The block current attribute configuration, keyed to the attribute name.
* @param \WPGraphQL\ContentBlocks\Model\Block $block The block model instance.
* @param array<string,mixed> $attribute_configs The block current attribute configuration, keyed to the attribute name.
*/
private function resolve_block_attributes_recursive( $attribute_values, string $html, array $attribute_configs ): array {
private function resolve_block_attributes_recursive( BlockModel $block, array $attribute_configs ): array {
$result = [];

// Clean up the html.
$html = trim( $html );
$html = isset( $block->renderedHtml ) ? trim( $block->renderedHtml ) : '';

foreach ( $attribute_configs as $key => $config ) {
$attribute_value = $attribute_values[ $key ] ?? null;
$attribute_value = $block->parsedAttributes[ $key ] ?? null;

$result[ $key ] = BlockAttributeResolver::resolve_block_attribute( $config, $html, $attribute_value );
}
Expand Down
3 changes: 2 additions & 1 deletion includes/Blocks/CoreImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ public function __construct( WP_Block_Type $block, Registry $block_registry ) {
$this->type_name
),
'resolve' => static function ( $block ) {
$attrs = $block['attrs'];
$attrs = $block->parsedAttributes ?? [];
$id = $attrs['id'] ?? null;

if ( $id ) {
$media_details = wp_get_attachment_metadata( $id );
if ( ! empty( $media_details ) ) {
Expand Down
12 changes: 9 additions & 3 deletions includes/Data/ContentBlocksResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace WPGraphQL\ContentBlocks\Data;

use WPGraphQL\ContentBlocks\Model\Block;
use WPGraphQL\Model\Post;

/**
Expand All @@ -20,7 +21,7 @@ final class ContentBlocksResolver {
* @param array<string,mixed> $args GraphQL query args to pass to the connection resolver.
* @param string[] $allowed_block_names The list of allowed block names to filter.
*
* @return array<string,mixed> The resolved parsed blocks.
* @return \WPGraphQL\ContentBlocks\Model\Block[]
*/
public static function resolve_content_blocks( $node, $args, $allowed_block_names = [] ): array {
/**
Expand All @@ -39,7 +40,6 @@ public static function resolve_content_blocks( $node, $args, $allowed_block_name

$content = null;
if ( $node instanceof Post ) {

// @todo: this is restricted intentionally.
// $content = $node->contentRaw;

Expand Down Expand Up @@ -88,7 +88,13 @@ public static function resolve_content_blocks( $node, $args, $allowed_block_name
*/
$parsed_blocks = apply_filters( 'wpgraphql_content_blocks_resolve_blocks', $parsed_blocks, $node, $args, $allowed_block_names );

return is_array( $parsed_blocks ) ? $parsed_blocks : [];
// Map the blocks to the Block model
return is_array( $parsed_blocks ) ? array_map(
static function ( $parsed_block ) {
return new Block( new \WP_Block( $parsed_block ) );
},
$parsed_blocks
) : [];
}

/**
Expand Down
4 changes: 3 additions & 1 deletion includes/Field/BlockSupports/Anchor.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ public static function register(): void {
'type' => 'string',
'description' => __( 'The anchor field for the block.', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
$rendered_block = wp_unslash( render_block( $block ) );
$rendered_block = wp_unslash( $block->renderedHtml );

if ( empty( $rendered_block ) ) {
return null;
}

return DOMHelpers::parse_first_node_attribute( $rendered_block, 'id' );
},
],
Expand Down
167 changes: 167 additions & 0 deletions includes/Model/Block.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php
/**
* A GraphQL Model for a WordPress Block.
*
* @package WPGraphQL\ContentBlocks\Model
*
* @since @todo
*/

namespace WPGraphQL\ContentBlocks\Model;

use WPGraphQL\ContentBlocks\Data\BlockAttributeResolver;
use WPGraphQL\ContentBlocks\Utilities\WPGraphQLHelpers;
use WPGraphQL\Model\Model;

/**
* Class - Block
*
* @property ?string $clientId
* @property ?string $parentClientId
* @property ?string $name
* @property ?string $blockEditorCategoryName
* @property bool $isDynamic
* @property ?int $apiVersion
* @property ?string[] $cssClassNames
* @property ?string $renderedHtml
* @property self[] $innerBlocks
* @property array<string,mixed> $parsedAttributes
* @property ?string $type
* @property \WP_Block $wpBlock
*/
class Block extends Model {
/**
* The underlying \WP_Block instance for the block data.
*
* @var \WP_Block
*/
protected $data;

/**
* The rendered block html.
*
* @var ?string
*/
protected $rendered_block;

/**
* {@inheritDoc}
*
* @param \WP_Block $block The block data to be modeled.
*/
public function __construct( \WP_Block $block ) {
$this->data = $block;

// Log a Debug message if the block type is not found.
if ( ! $this->data->block_type ) {
graphql_debug(
sprintf(
__( 'Block type not found for block: %s', 'wp-graphql-content-blocks' ),
$this->data->name ?: 'Unknown'
),
[
'parsed_block' => $block,
]
);
}

parent::__construct();
}

/**
* {@inheritDoc}
*/
protected function is_private() {
return false;
}

/**
* {@inheritDoc}
*/
protected function init() {
if ( empty( $this->fields ) ) {
$this->fields = [
'clientId' => fn (): ?string => $this->data->parsed_block['clientId'] ?? uniqid(),
'parentClientId' => fn (): ?string => $this->data->parsed_block['parentClientId'] ?? null,
'name' => fn (): ?string => $this->data->name ?: null,
'blockEditorCategoryName' => fn () => isset( $this->data->block_type->category ) ? $this->data->block_type->category : null,
'isDynamic' => fn (): bool => is_callable( $this->data->block_type->render_callback ),
'apiVersion' => fn (): ?int => $this->data->block_type->api_version ?: null,
'cssClassNames' => fn (): ?array => isset( $this->data->attributes['className'] ) ? explode( ' ', $this->data->attributes['className'] ) : null,
'renderedHtml' => fn (): ?string => $this->get_rendered_block(),
'innerBlocks' => function (): array {
$block_list = $this->data->inner_blocks ?: [];

$models_to_return = [];

foreach ( $block_list as $block ) {
$models_to_return[] = new self( $block );
}

return $models_to_return;
},
'parsedAttributes' => fn (): array => $this->data->attributes,
'type' => function (): ?string {
$block_name = $this->name ?? null;

return isset( $block_name ) ? WPGraphQLHelpers::format_type_name( $block_name ) : null;
},
'wpBlock' => function (): \WP_Block {
return $this->data;
},
];
}
}

/**
* Renders the block html - only once.
*
* The `render_block()` function causes side effects (such as globally-incrementing the counter used for layout styles), so we only want to call it once.
*/
protected function get_rendered_block(): ?string {
if ( ! isset( $this->rendered_block ) ) {
$rendered = $this->data->render();
$this->rendered_block = do_shortcode( $rendered );
}

return $this->rendered_block;
}

/**
* Resolves the block attributes.
*
* @return array<string,callable(string,array<string,mixed>):mixed>
*/
protected function resolve_attributes(): array {
$registered_attributes = $this->data->block_type->attributes ?? [];

$resolvers = [];

foreach ( array_keys( $registered_attributes ) as $attribute_name ) {
$resolvers[ $attribute_name ] = fn () => $this->resolve_attribute( $attribute_name );
}

return $resolvers;
}

/**
* Resolves a single block attribute.
*
* @param string $attribute_name The name of the attribute being resolved.
*
* @return mixed
*/
protected function resolve_attribute( string $attribute_name ) {
$attribute_config = $this->data->block_type->attributes[ $attribute_name ] ?? [];

return BlockAttributeResolver::resolve_block_attribute( $attribute_config, $this->get_rendered_block(), $this->data->attributes[ $attribute_name ] );

Check failure on line 157 in includes/Model/Block.php

View workflow job for this annotation

GitHub Actions / phpstan

Parameter #2 $html of static method WPGraphQL\ContentBlocks\Data\BlockAttributeResolver::resolve_block_attribute() expects string, string|null given.

$allowed_types = [ 'array', 'object', 'string', 'number', 'integer', 'boolean', 'null' ];

Check failure on line 159 in includes/Model/Block.php

View workflow job for this annotation

GitHub Actions / phpstan

Unreachable statement - code above always terminates.
// If attribute type is set and valid, sanitize value.
if ( isset( $attribute['type'] ) && in_array( $attribute_config['type'], $allowed_types, true ) && rest_validate_value_from_schema( $result, $attribute_config ) ) {
$result = rest_sanitize_value_from_schema( $result, $attribute_config );
}

return $result;
}
}
30 changes: 2 additions & 28 deletions includes/Type/InterfaceType/EditorBlockInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
namespace WPGraphQL\ContentBlocks\Type\InterfaceType;

use WPGraphQL\ContentBlocks\Data\ContentBlocksResolver;
use WPGraphQL\ContentBlocks\Utilities\WPGraphQLHelpers;
use WP_Block_Type_Registry;

/**
Expand Down Expand Up @@ -75,16 +74,10 @@ public static function register_type(): void {
'clientId' => [
'type' => 'String',
'description' => __( 'The id of the Block', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return isset( $block['clientId'] ) ? $block['clientId'] : uniqid();
},
],
'parentClientId' => [
'type' => 'String',
'description' => __( 'The parent id of the Block', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return isset( $block['parentClientId'] ) ? $block['parentClientId'] : null;
},
],
'name' => [
'type' => 'String',
Expand All @@ -93,58 +86,39 @@ public static function register_type(): void {
'blockEditorCategoryName' => [
'type' => 'String',
'description' => __( 'The name of the category the Block belongs to', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return isset( self::get_block( $block )->category ) ? self::get_block( $block )->category : null;
},
],
'isDynamic' => [
'type' => [ 'non_null' => 'Boolean' ],
'description' => __( 'Whether the block is Dynamic (server rendered)', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return isset( self::get_block( $block )->render_callback );
},
],
'apiVersion' => [
'type' => 'Integer',
'description' => __( 'The API version of the Gutenberg Block', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return isset( self::get_block( $block )->api_version ) && absint( self::get_block( $block )->api_version ) ? absint( self::get_block( $block )->api_version ) : 2;
return $block->apiVersion ?? 2;
},
],
'innerBlocks' => [
'type' => [
'list_of' => 'EditorBlock',
],
'description' => __( 'The inner blocks of the Block', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return isset( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) ? $block['innerBlocks'] : [];
},
],
'cssClassNames' => [
'type' => [ 'list_of' => 'String' ],
'description' => __( 'CSS Classnames to apply to the block', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
if ( isset( $block['attrs']['className'] ) ) {
return explode( ' ', $block['attrs']['className'] );
}

return null;
},
],
'renderedHtml' => [
'type' => 'String',
'description' => __( 'The rendered HTML for the block', 'wp-graphql-content-blocks' ),
'resolve' => static function ( $block ) {
return render_block( $block );
},
],
'type' => [
'type' => 'String',
'description' => __( 'The (GraphQL) type of the block', 'wp-graphql-content-blocks' ),
],
],
'resolveType' => static function ( $block ) {
return WPGraphQLHelpers::get_type_name_for_block( $block['blockName'] ?? null );
return $block->type;
},
]
);
Expand Down
Loading

0 comments on commit bddd798

Please sign in to comment.