351 lines
12 KiB
PHP
351 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Gutenberg Block Registration
|
|
* Registers the GitHub Code Viewer block for the block editor
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('WPINC')) {
|
|
die('Direct access not permitted.');
|
|
}
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class MCB_Block_Editor {
|
|
|
|
/**
|
|
* Initialize block editor support
|
|
*/
|
|
public static function init() {
|
|
// Check if Gutenberg is available
|
|
if (!function_exists('register_block_type')) {
|
|
return;
|
|
}
|
|
|
|
add_action('init', array(__CLASS__, 'register_block'));
|
|
add_action('enqueue_block_editor_assets', array(__CLASS__, 'enqueue_block_editor_assets'));
|
|
add_action('enqueue_block_assets', array(__CLASS__, 'enqueue_block_assets'));
|
|
add_filter('block_categories_all', array(__CLASS__, 'add_block_category'), 10, 2);
|
|
}
|
|
|
|
/**
|
|
* Register the block
|
|
*/
|
|
public static function register_block() {
|
|
// Debug: Log that we're attempting to register
|
|
error_log('MCB: Attempting to register block');
|
|
|
|
// Register block editor script
|
|
wp_register_script(
|
|
'mcb-block-editor',
|
|
MCB_PLUGIN_URL . 'assets/js/block-editor.js',
|
|
array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-data'),
|
|
MCB_PLUGIN_VERSION,
|
|
true
|
|
);
|
|
|
|
// Register block editor styles
|
|
wp_register_style(
|
|
'mcb-block-editor-style',
|
|
MCB_PLUGIN_URL . 'assets/css/block-editor.css',
|
|
array('wp-edit-blocks'),
|
|
MCB_PLUGIN_VERSION
|
|
);
|
|
|
|
// Register the block with simplified attributes first
|
|
$result = register_block_type('maple-code-blocks/code-block', array(
|
|
'editor_script' => 'mcb-block-editor',
|
|
'editor_style' => 'mcb-block-editor-style',
|
|
'render_callback' => array(__CLASS__, 'render_block'),
|
|
'attributes' => array(
|
|
'repository' => array(
|
|
'type' => 'string',
|
|
'default' => ''
|
|
),
|
|
'theme' => array(
|
|
'type' => 'string',
|
|
'default' => 'dark'
|
|
),
|
|
'height' => array(
|
|
'type' => 'string',
|
|
'default' => '600px'
|
|
),
|
|
'showLineNumbers' => array(
|
|
'type' => 'boolean',
|
|
'default' => true
|
|
),
|
|
'initialFile' => array(
|
|
'type' => 'string',
|
|
'default' => ''
|
|
),
|
|
'title' => array(
|
|
'type' => 'string',
|
|
'default' => ''
|
|
),
|
|
'align' => array(
|
|
'type' => 'string',
|
|
'default' => 'none'
|
|
),
|
|
'className' => array(
|
|
'type' => 'string',
|
|
'default' => ''
|
|
)
|
|
),
|
|
'supports' => array(
|
|
'align' => array('wide', 'full'),
|
|
'className' => true,
|
|
'customClassName' => true,
|
|
'html' => false,
|
|
'anchor' => true
|
|
),
|
|
'example' => array(
|
|
'attributes' => array(
|
|
'repository' => 'facebook/react',
|
|
'theme' => 'dark',
|
|
'height' => '400px',
|
|
'title' => 'React Source Code Example'
|
|
)
|
|
)
|
|
));
|
|
|
|
// Add block variations
|
|
wp_register_script(
|
|
'mcb-block-variations',
|
|
MCB_PLUGIN_URL . 'assets/js/block-variations.js',
|
|
array('wp-blocks', 'wp-dom-ready'),
|
|
MCB_PLUGIN_VERSION,
|
|
true
|
|
);
|
|
|
|
wp_enqueue_script('mcb-block-variations');
|
|
}
|
|
|
|
/**
|
|
* Render the block on the frontend
|
|
*/
|
|
public static function render_block($attributes, $content) {
|
|
// Validate required attributes
|
|
if (empty($attributes['repository'])) {
|
|
return '<div class="mcb-error">Please specify a repository (e.g., owner/repository)</div>';
|
|
}
|
|
|
|
// Sanitize attributes
|
|
$repository = sanitize_text_field($attributes['repository']);
|
|
|
|
// Validate repository format
|
|
if (!MCB_Security::validate_repo_format($repository)) {
|
|
return '<div class="mcb-error">Invalid repository format. Use: owner/repository</div>';
|
|
}
|
|
|
|
// Build shortcode attributes
|
|
$shortcode_atts = array(
|
|
'repo' => $repository,
|
|
'theme' => sanitize_text_field($attributes['theme'] ?? 'dark'),
|
|
'height' => sanitize_text_field($attributes['height'] ?? '600px'),
|
|
'show_line_numbers' => $attributes['showLineNumbers'] ? 'true' : 'false',
|
|
'initial_file' => sanitize_text_field($attributes['initialFile'] ?? ''),
|
|
'title' => sanitize_text_field($attributes['title'] ?? '')
|
|
);
|
|
|
|
// Add alignment class if needed
|
|
$wrapper_class = 'mcb-block-wrapper';
|
|
if (!empty($attributes['align'])) {
|
|
$wrapper_class .= ' align' . esc_attr($attributes['align']);
|
|
}
|
|
if (!empty($attributes['className'])) {
|
|
$wrapper_class .= ' ' . esc_attr($attributes['className']);
|
|
}
|
|
|
|
// Generate shortcode
|
|
$shortcode = '[maple_code_block';
|
|
foreach ($shortcode_atts as $key => $value) {
|
|
if (!empty($value)) {
|
|
$shortcode .= ' ' . $key . '="' . esc_attr($value) . '"';
|
|
}
|
|
}
|
|
$shortcode .= ']';
|
|
|
|
// Render with wrapper
|
|
return sprintf(
|
|
'<div class="%s">%s</div>',
|
|
esc_attr($wrapper_class),
|
|
do_shortcode($shortcode)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Enqueue block editor assets
|
|
*/
|
|
public static function enqueue_block_editor_assets() {
|
|
// Debug log
|
|
error_log('MCB: Enqueueing block editor assets');
|
|
|
|
// Make sure our script is registered
|
|
if (!wp_script_is('mcb-block-editor', 'registered')) {
|
|
error_log('MCB: Script not registered, registering now');
|
|
wp_register_script(
|
|
'mcb-block-editor',
|
|
MCB_PLUGIN_URL . 'assets/js/block-editor.js',
|
|
array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-data'),
|
|
MCB_PLUGIN_VERSION,
|
|
true
|
|
);
|
|
}
|
|
|
|
// Localize script with data for the editor
|
|
wp_localize_script('mcb-block-editor', 'mcbBlockData', array(
|
|
'pluginUrl' => MCB_PLUGIN_URL,
|
|
'themes' => array(
|
|
array('label' => 'Dark', 'value' => 'dark'),
|
|
array('label' => 'Light', 'value' => 'light'),
|
|
array('label' => 'Monokai', 'value' => 'monokai'),
|
|
array('label' => 'Solarized', 'value' => 'solarized')
|
|
),
|
|
'defaultHeight' => '600px',
|
|
'popularRepos' => array(
|
|
'facebook/react',
|
|
'vuejs/vue',
|
|
'angular/angular',
|
|
'microsoft/vscode',
|
|
'torvalds/linux',
|
|
'tensorflow/tensorflow',
|
|
'kubernetes/kubernetes',
|
|
'nodejs/node',
|
|
'rust-lang/rust',
|
|
'golang/go'
|
|
),
|
|
'nonce' => wp_create_nonce('mcb_block_nonce')
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Enqueue frontend block assets
|
|
*/
|
|
public static function enqueue_block_assets() {
|
|
// Only enqueue on frontend
|
|
if (!is_admin()) {
|
|
// These will be enqueued by the shortcode handler
|
|
// We just need to ensure the block wrapper styles are loaded
|
|
wp_enqueue_style(
|
|
'mcb-block-style',
|
|
MCB_PLUGIN_URL . 'assets/css/block-style.css',
|
|
array(),
|
|
MCB_PLUGIN_VERSION
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add custom block category
|
|
*/
|
|
public static function add_block_category($categories, $post) {
|
|
return array_merge(
|
|
array(
|
|
array(
|
|
'slug' => 'maple-code-blocks',
|
|
'title' => __('Maple Code Blocks', 'maple-code-blocks'),
|
|
'icon' => 'editor-code'
|
|
)
|
|
),
|
|
$categories
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Register REST API endpoint for repository validation
|
|
*/
|
|
public static function register_rest_routes() {
|
|
register_rest_route('maple-code-blocks/v1', '/validate-repo', array(
|
|
'methods' => 'POST',
|
|
'callback' => array(__CLASS__, 'validate_repository'),
|
|
'permission_callback' => function() {
|
|
return current_user_can('edit_posts');
|
|
},
|
|
'args' => array(
|
|
'repository' => array(
|
|
'required' => true,
|
|
'type' => 'string',
|
|
'sanitize_callback' => 'sanitize_text_field'
|
|
)
|
|
)
|
|
));
|
|
|
|
register_rest_route('maple-code-blocks/v1', '/get-files', array(
|
|
'methods' => 'POST',
|
|
'callback' => array(__CLASS__, 'get_repository_files'),
|
|
'permission_callback' => function() {
|
|
return current_user_can('edit_posts');
|
|
},
|
|
'args' => array(
|
|
'repository' => array(
|
|
'required' => true,
|
|
'type' => 'string',
|
|
'sanitize_callback' => 'sanitize_text_field'
|
|
)
|
|
)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Validate repository via REST API
|
|
*/
|
|
public static function validate_repository($request) {
|
|
$repository = $request->get_param('repository');
|
|
|
|
// Validate format
|
|
if (!MCB_Security::validate_repo_format($repository)) {
|
|
return new WP_Error('invalid_format', 'Invalid repository format. Use: owner/repository');
|
|
}
|
|
|
|
// Quick check with GitHub API
|
|
$github_api = new MCB_GitHub_API();
|
|
$result = $github_api->validate_repository_exists($repository);
|
|
|
|
if (is_wp_error($result)) {
|
|
return $result;
|
|
}
|
|
|
|
return array(
|
|
'valid' => true,
|
|
'repository' => $repository
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get repository files for block editor preview
|
|
*/
|
|
public static function get_repository_files($request) {
|
|
$repository = $request->get_param('repository');
|
|
|
|
// Validate format
|
|
if (!MCB_Security::validate_repo_format($repository)) {
|
|
return new WP_Error('invalid_format', 'Invalid repository format');
|
|
}
|
|
|
|
$github_api = new MCB_GitHub_API();
|
|
$files = $github_api->get_repository_files($repository);
|
|
|
|
if (is_wp_error($files)) {
|
|
return $files;
|
|
}
|
|
|
|
// Return only file names for the editor
|
|
$file_list = array_map(function($file) {
|
|
return array(
|
|
'path' => $file['path'],
|
|
'name' => $file['name']
|
|
);
|
|
}, array_slice($files, 0, 10)); // Limit to 10 files for preview
|
|
|
|
return array(
|
|
'files' => $file_list,
|
|
'total' => count($files)
|
|
);
|
|
}
|
|
}
|
|
|
|
// Initialize block editor support
|
|
add_action('init', array('MCB_Block_Editor', 'init'));
|
|
add_action('rest_api_init', array('MCB_Block_Editor', 'register_rest_routes'));
|