Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
robertdevore committed Nov 8, 2024
1 parent 185355b commit 0a56b18
Show file tree
Hide file tree
Showing 116 changed files with 11,291 additions and 2 deletions.
50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,48 @@
# block-usage-tracker
A plugin that lists active blocks on the site and counts their usage.
# Block Usage Tracker
**Block Usage Tracker** is a WordPress® admin tool designed to help content managers and developers monitor block usage across a site.

The plugin lists each block type used in posts, counting the total occurrences and shows direct links to each post where a block appears.

This functionality helps teams optimize content, understand block usage patterns, and maintain consistency.

## Features

- Lists all active blocks across posts and their usage counts.
- Displays links to each page/post where blocks are used.
- Excludes duplicate links for better readability.
- Caches block usage data for efficient, optimized performance.
- User-friendly modal interface for viewing detailed block usage by post.
- Designed with proper security and access restrictions.

## Installation

### From the WordPress® Admin Dashboard

1. Download the latest release from [GitHub](https://github.com/robertdevore/block-usage-tracker).
2. In your WordPress® dashboard, go to **Plugins > Add New**.
3. Click **Upload Plugin** and choose the downloaded ZIP file.
4. Install and activate the plugin.

### Manual Installation

1. Download the plugin files and extract the ZIP.
2. Upload the extracted folder to `/wp-content/plugins/block-usage-tracker`.
3. Activate the plugin through the **Plugins** menu in WordPress®.

## Usage

1. Once activated, go to **Settings > Block Usage Tracker** in your WordPress® admin.
2. You'll see a table with each block type, its total usage count, and a **View Details** button.
3. Click **View Details** for any block to open a modal with links to each post where that block is used.

## Contributing

We welcome contributions to improve **Block Usage Tracker**! Here's how you can help:

1. Fork the repository.
2. Create a new branch (`git checkout -b feature-branch-name`).
3. Commit your changes (`git commit -am 'Add new feature or fix'`).
4. Push to the branch (`git push origin feature-branch-name`).
5. Open a pull request.

For bug reports or feature requests, please open an issue in this repository.
203 changes: 203 additions & 0 deletions block-usage-tracker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
<?php
/**
* The plugin bootstrap file
*
* @link https://robertdevore.com
* @since 1.0.0
* @package Block_Usage_Tracker
*
* @wordpress-plugin
*
* Plugin Name: Block Usage Tracker
* Description: A plugin that lists active blocks on the site and counts their usage.
* Plugin URI: https://github.com/robertdevore/block-usage-tracker/
* Version: 1.0.0
* Author: Robert DeVore
* Author URI: https://robertdevore.com/
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: block-usage-tracker
* Domain Path: /languages
* Update URI: https://github.com/robertdevore/block-usage-tracker/
*/

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}

require 'vendor/plugin-update-checker/plugin-update-checker.php';
use YahnisElsts\PluginUpdateChecker\v5\PucFactory;

$myUpdateChecker = PucFactory::buildUpdateChecker(
'https://github.com/robertdevore/block-usage-tracker/',
__FILE__,
'block-usage-tracker'
);

// Set the branch that contains the stable release.
$myUpdateChecker->setBranch( 'main' );

/**
* Current plugin version.
*/
define( 'BLOCK_USAGE_TRACKER_VERSION', '1.0.0' );

class BlockUsageTracker {

public function __construct() {
add_action( 'admin_menu', [ $this, 'add_admin_menu' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );
add_action( 'admin_init', [ $this, 'track_block_usage' ] );
}

public function add_admin_menu() {
add_options_page(
esc_html__( 'Block Usage Tracker', 'block-usage-tracker' ),
esc_html__( 'Block Usage Tracker', 'block-usage-tracker' ),
'manage_options',
'block-usage-tracker',
[ $this, 'display_settings_page' ]
);
}

public function enqueue_admin_scripts() {
wp_enqueue_style( 'block-usage-tracker-styles', plugin_dir_url( __FILE__ ) . 'style.css', [], BLOCK_USAGE_TRACKER_VERSION );
wp_enqueue_script( 'block-usage-tracker-scripts', plugin_dir_url( __FILE__ ) . 'script.js', [ 'jquery' ], BLOCK_USAGE_TRACKER_VERSION, true );
}

public function display_settings_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}

echo '<div class="wrap"><h1>' . esc_html__( 'Active Block Usage', 'block-usage-tracker' ) . '</h1>';

$table = new BlockUsageTable();
$table->prepare_items();
$table->display();

echo '</div>';

// Modal container for displaying post links
echo '<div id="block-usage-modal" class="block-usage-modal">
<div class="block-usage-modal-content">
<span class="block-usage-close">&times;</span>
<h2>' . esc_html__( 'Block Usage Details', 'block-usage-tracker' ) . '</h2>
<div id="block-usage-modal-body"></div>
</div>
</div>';
}

public function track_block_usage() {
// Initialize block counts and posts arrays
$block_counts = get_transient( 'block_usage_counts' );
$block_posts = get_transient( 'block_usage_posts' );

// Check if transients already exist; if not, calculate block usage
if ( false === $block_counts || false === $block_posts ) {
$block_counts = [];
$block_posts = [];

$posts = get_posts(
[
'post_type' => 'post',
'numberposts' => -1,
'post_status' => 'publish',
]
);

foreach ( $posts as $post ) {
$blocks = parse_blocks( $post->post_content );

foreach ( $blocks as $block ) {
$block_name = $block['blockName'] ? $block['blockName'] : 'core/unknown';

if ( isset( $block_counts[ $block_name ] ) ) {
$block_counts[ $block_name ]++;
} else {
$block_counts[ $block_name ] = 1;
}

// Track post titles and links where this block is used
$block_posts[ $block_name ][] = [
'title' => get_the_title( $post->ID ),
'url' => get_permalink( $post->ID ),
];
}
}

// Set the transients
set_transient( 'block_usage_counts', $block_counts, DAY_IN_SECONDS );
set_transient( 'block_usage_posts', $block_posts, DAY_IN_SECONDS );
}

// Store the counts and posts data in the global variable for use in the table
$GLOBALS['block_usage_counts'] = $block_counts;
$GLOBALS['block_usage_posts'] = $block_posts;
}

}

if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class BlockUsageTable extends WP_List_Table {

public function __construct() {
parent::__construct(
[
'singular' => 'block',
'plural' => 'blocks',
'ajax' => false,
]
);
}

public function prepare_items() {
$columns = $this->get_columns();
$this->_column_headers = [ $columns, [], [] ];

$this->items = [];
foreach ( $GLOBALS['block_usage_counts'] as $block_name => $count ) {
$this->items[] = [
'name' => $block_name,
'count' => $count,
'posts' => $GLOBALS['block_usage_posts'][ $block_name ] ?? [],
];
}
}

public function get_columns() {
return [
'name' => esc_html__( 'Block Type', 'block-usage-tracker' ),
'count' => esc_html__( 'Usage Count', 'block-usage-tracker' ),
'view_details' => esc_html__( 'Details', 'block-usage-tracker' ),
];
}

public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'name':
return esc_html( $item['name'] );
case 'count':
return esc_html( number_format_i18n( $item['count'] ) );
case 'view_details':
// Properly JSON encode the posts data for HTML attribute use
$posts_json = ! empty( $item['posts'] ) ? wp_json_encode( $item['posts'] ) : '[]';

return sprintf(
'<a href="#" class="view-details-button" data-block="%s" data-posts="%s">%s</a>',
esc_attr( $item['name'] ),
esc_attr( $posts_json ),
esc_html__( 'View Details', 'block-usage-tracker' )
);
default:
return '';
}
}

}

new BlockUsageTracker();
51 changes: 51 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
jQuery(document).ready(function ($) {
$('.view-details-button').on('click', function (e) {
e.preventDefault();

let blockName = $(this).data('block');
let postsData = $(this).data('posts'); // Directly access data without JSON.parse()
let modalBody = $('#block-usage-modal-body');

// Clear the modal content from any previous usage
modalBody.empty();

// Display a summary message at the top
let usageCount = postsData.length;
modalBody.append('<p><strong>The ' + blockName + ' block was found ' + usageCount + ' times in the following content:</strong></p>');

// Filter unique URLs to avoid duplicates
let uniquePosts = [];
let uniqueUrls = new Set();

postsData.forEach(post => {
if (!uniqueUrls.has(post.url)) {
uniqueUrls.add(post.url);
uniquePosts.push(post);
}
});

// Display each unique post
if (uniquePosts.length > 0) {
uniquePosts.forEach(post => {
modalBody.append('<p><a href="' + post.url + '" target="_blank">' + post.title + '</a></p>');
});
} else {
modalBody.append('<p>No posts found for this block.</p>');
}

// Show the modal
$('#block-usage-modal').fadeIn();
});

// Close the modal when the close button is clicked
$('.block-usage-close').on('click', function () {
$('#block-usage-modal').fadeOut();
});

// Close the modal when clicking outside of the modal content
$(window).on('click', function (e) {
if ($(e.target).is('#block-usage-modal')) {
$('#block-usage-modal').fadeOut();
}
});
});
30 changes: 30 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.block-usage-modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.7);
}

.block-usage-modal-content {
background-color: #fff;
margin: 10% auto;
padding: 20px;
width: 80%;
max-width: 600px;
border-radius: 8px;
position: relative;
}

.block-usage-close {
position: absolute;
top: 10px;
right: 20px;
color: #000;
font-size: 24px;
cursor: pointer;
}
10 changes: 10 additions & 0 deletions vendor/plugin-update-checker/Puc/v5/PucFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace YahnisElsts\PluginUpdateChecker\v5;

if ( !class_exists(PucFactory::class, false) ):

class PucFactory extends \YahnisElsts\PluginUpdateChecker\v5p4\PucFactory {
}

endif;
Loading

0 comments on commit 0a56b18

Please sign in to comment.