-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PLANET-7527 Move blocks report into master theme
- Loading branch information
1 parent
c5985de
commit dfcb5cd
Showing
27 changed files
with
3,634 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,292 @@ | ||
<?php | ||
|
||
/** | ||
* Table displaying blocks usage | ||
* | ||
* @package P4BKS\Controllers | ||
*/ | ||
|
||
namespace P4\MasterTheme\BlockReportSearch\Block; | ||
|
||
use WP_Block_Parser; | ||
use P4\MasterTheme\BlockReportSearch\BlockSearch; | ||
use P4\MasterTheme\BlockReportSearch\Block\Query\Parameters; | ||
|
||
/** | ||
* Present block usage, using native WordPress table | ||
*/ | ||
class BlockUsage | ||
{ | ||
/** | ||
* @var BlockSearch | ||
*/ | ||
private $search; | ||
|
||
/** | ||
* @var WP_Block_Parser | ||
*/ | ||
private $parser; | ||
|
||
/** | ||
* @var int[] | ||
*/ | ||
private $posts_ids; | ||
|
||
/** | ||
* @var WP_Post[] | ||
*/ | ||
private $posts; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
private $blocks; | ||
|
||
/** | ||
* @param BlockSearch $search Search class. | ||
* @param WP_Block_Parser $parser Block parser. | ||
*/ | ||
public function __construct( | ||
?BlockSearch $search = null, | ||
?WP_Block_Parser $parser = null | ||
) { | ||
$this->search = $search ?? new BlockSearch(); | ||
$this->parser = $parser ?? new WP_Block_Parser(); | ||
} | ||
|
||
/** | ||
* @param Parameters $params Query parameters. | ||
* @return array | ||
*/ | ||
public function get_blocks(Parameters $params): array | ||
{ | ||
$this->posts_ids = $this->search->get_posts($params); | ||
|
||
return $this->get_filtered_blocks($this->posts_ids, $params); | ||
} | ||
|
||
/** | ||
* @param Parameters $params Query parameters. | ||
* @return int[] | ||
*/ | ||
public function get_posts(Parameters $params): array | ||
{ | ||
$block_list = $this->get_blocks($this->posts_ids, $params); | ||
|
||
return array_unique(array_column($block_list, 'post_id')); | ||
} | ||
|
||
/** | ||
* @param int[] $posts_ids Posts IDs. | ||
* @param Parameters $params Query parameters. | ||
* @return array | ||
*/ | ||
private function get_filtered_blocks($posts_ids, Parameters $params) | ||
{ | ||
$this->fetch_blocks($posts_ids, $params); | ||
$this->filter_blocks($params); | ||
$this->sort_blocks($params->order()); | ||
|
||
return $this->blocks; | ||
} | ||
|
||
/** | ||
* @param int[] $posts_ids Posts IDs. | ||
* @param Parameters $params Query parameters. | ||
*/ | ||
private function fetch_blocks(array $posts_ids, Parameters $params): void | ||
{ | ||
$posts_args = [ | ||
'include' => $posts_ids, | ||
'orderby' => empty($params->order()) ? null : array_fill_keys($params->order(), 'ASC'), | ||
'post_status' => $params->post_status(), | ||
'post_type' => $params->post_type(), | ||
]; | ||
|
||
$this->posts = get_posts($posts_args) ?? []; | ||
|
||
$block_listblock_list = []; | ||
foreach ($this->posts as $post) { | ||
$block_listblock_list = array_merge($block_listblock_list, $this->parse_post($post)); | ||
} | ||
$this->blocks = $block_listblock_list; | ||
} | ||
|
||
/** | ||
* Filter parsed search items | ||
* | ||
* @param Parameters $params Query parameters. | ||
* @return array | ||
*/ | ||
private function filter_blocks(Parameters $params): void | ||
{ | ||
if ( | ||
empty($params->namespace()) | ||
&& empty($params->name()) | ||
&& empty($params->content()) | ||
) { | ||
return; | ||
} | ||
|
||
$filtered = $this->blocks; | ||
|
||
$text = $params->content(); | ||
$filters = [ | ||
'block_ns' => $params->namespace(), | ||
'block_type' => $params->name(), | ||
'local_name' => false !== strpos($params->name(), '/') | ||
? explode('/', $params->name())[1] | ||
: $params->name(), | ||
]; | ||
|
||
if (! empty($filters['block_type'])) { | ||
$filtered = array_filter( | ||
$filtered, | ||
function ($i) use ($filters) { | ||
return $i['block_type'] === $filters['block_type'] | ||
|| $i['local_name'] === $filters['local_name']; | ||
} | ||
); | ||
} elseif (! empty($filters['block_ns'])) { | ||
$filtered = array_filter( | ||
$filtered, | ||
function ($i) use ($filters) { | ||
return $i['block_ns'] === $filters['block_ns']; | ||
} | ||
); | ||
} | ||
|
||
if (! empty($text)) { | ||
$filtered = array_filter( | ||
$filtered, | ||
function ($i) use ($text) { | ||
return strpos($i['block_type'], $text) !== false | ||
//phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize | ||
|| strpos(serialize($i['block_attrs']), $text) !== false; | ||
} | ||
); | ||
} | ||
|
||
$this->blocks = $filtered; | ||
} | ||
|
||
/** | ||
* Sort parsed blocks | ||
* | ||
* @param null|array $sort Sort dimensions. | ||
* @return array | ||
*/ | ||
private function sort_blocks(?array $sort = []): void | ||
{ | ||
if (empty($sort)) { | ||
return; | ||
} | ||
|
||
$args = []; | ||
$block_list = $this->blocks; | ||
foreach ($sort as $name) { | ||
$args[] = array_column($block_list, $name); | ||
$args[] = SORT_NATURAL; | ||
} | ||
$args[] = &$block_list; | ||
|
||
array_multisort(...$args); | ||
|
||
$this->blocks = $block_list; | ||
} | ||
|
||
/** | ||
* Parse posts content to blocks. | ||
* | ||
* @param object $post WP_Post. | ||
* @return array[] | ||
*/ | ||
private function parse_post($post): array | ||
{ | ||
$output = $this->parser->parse($post->post_content); | ||
|
||
$block_list = array_filter( | ||
$output, | ||
function ($block) { | ||
return ! empty($block['blockName']); | ||
} | ||
); | ||
|
||
$items = []; | ||
while (! empty($block_list)) { | ||
$block = array_shift($block_list); | ||
$items[] = $this->format_block_data($block, $post); | ||
|
||
if (empty($block['innerBlocks'])) { | ||
continue; | ||
} | ||
|
||
$block_list = array_merge($block_list, $block['innerBlocks']); | ||
} | ||
|
||
return $items; | ||
} | ||
|
||
/** | ||
* Format block information. | ||
* | ||
* @param array $block A block. | ||
* @param object $post WP_Post. | ||
* @return array[] | ||
*/ | ||
private function format_block_data(array $block, $post): array | ||
{ | ||
$type = $block['blockName']; | ||
$attrs = $block['attrs'] ?? []; | ||
$has_ns = strpos($type, '/') !== false; | ||
|
||
[ $namespace, $local_name ] = $has_ns ? explode('/', $type) : [ 'core', $type ]; | ||
|
||
$classes = empty($attrs['className']) ? [] : explode(' ', $attrs['className']); | ||
$styles = array_filter( | ||
array_map( | ||
function ($c): ?string { | ||
return 'is-style-' === substr($c, 0, 9) ? substr($c, 9) : null; | ||
}, | ||
$classes | ||
) | ||
); | ||
|
||
return [ | ||
'post_id' => $post->ID, | ||
'post_title' => $post->post_title | ||
? $post->post_title : __('(no title)', 'planet4-blocks-backend'), | ||
'post_status' => $post->post_status, | ||
'post_type' => $post->post_type, | ||
'post_date' => $post->post_date, | ||
'post_modified' => $post->post_modified, | ||
'post_status' => $post->post_status, | ||
'guid' => $post->guid, | ||
'block_ns' => $namespace, | ||
'block_type' => $type, | ||
'local_name' => $local_name, | ||
'block_attrs' => $attrs, | ||
'block_styles' => $styles, | ||
]; | ||
} | ||
|
||
/** | ||
* Block count in search result. | ||
* | ||
* @return int | ||
*/ | ||
public function block_count(): int | ||
{ | ||
return count($this->blocks); | ||
} | ||
|
||
/** | ||
* Post count in search result. | ||
* | ||
* @return int | ||
*/ | ||
public function post_count(): int | ||
{ | ||
return count($this->posts_ids); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<?php | ||
|
||
/** | ||
* Table displaying blocks usage | ||
* | ||
* @package P4BKS\Controllers | ||
*/ | ||
|
||
namespace P4\MasterTheme\BlockReportSearch\Block; | ||
|
||
use P4\MasterTheme\BlockReportSearch\Block\Query\Parameters; | ||
|
||
/** | ||
* Block usage API | ||
*/ | ||
class BlockUsageApi | ||
{ | ||
public const DEFAULT_POST_STATUS = [ 'publish' ]; | ||
|
||
private BlockUsage $usage; | ||
|
||
private Parameters $params; | ||
|
||
/** | ||
* @var array[] Blocks. | ||
*/ | ||
private $items; | ||
|
||
/** | ||
* Constructor | ||
*/ | ||
public function __construct() | ||
{ | ||
$this->usage = new BlockUsage(); | ||
$this->params = ( new Parameters() ) | ||
->with_post_status(self::DEFAULT_POST_STATUS) | ||
->with_post_type( | ||
\get_post_types( | ||
[ | ||
'public' => true, | ||
'exclude_from_search' => false, | ||
] | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Count blocks by type and style | ||
* | ||
* If style is not specified, an empty key 'n/a' is used. | ||
*/ | ||
public function get_count(): array | ||
{ | ||
if (null === $this->items) { | ||
$this->fetch_items(); | ||
} | ||
|
||
$types = array_unique( | ||
array_column($this->items, 'block_type') | ||
); | ||
$blocks = array_fill_keys( | ||
$types, | ||
[ | ||
'total' => 0, | ||
'styles' => [], | ||
] | ||
); | ||
ksort($blocks); | ||
|
||
foreach ($this->items as $item) { | ||
$styles = empty($item['block_styles']) ? [ 'n/a' ] : $item['block_styles']; | ||
foreach ($styles as $style) { | ||
$type = $item['block_type']; | ||
if (! isset($blocks[ $type ]['styles'][ $style ])) { | ||
$blocks[ $type ]['styles'][ $style ] = 0; | ||
} | ||
$blocks[ $type ]['styles'][ $style ]++; | ||
$blocks[ $type ]['total']++; | ||
} | ||
ksort($blocks[ $type ]['styles']); | ||
} | ||
|
||
return $blocks; | ||
} | ||
|
||
/** | ||
* Fetch parsed blocks | ||
*/ | ||
private function fetch_items(): void | ||
{ | ||
$this->items = $this->usage->get_blocks($this->params); | ||
} | ||
} |
Oops, something went wrong.