Plugin Directory

Changeset 3289104


Ignore:
Timestamp:
05/07/2025 11:43:22 AM (10 months ago)
Author:
blincks
Message:

Version 1.1

Location:
structure-viewer
Files:
12 added
7 edited

Legend:

Unmodified
Added
Removed
  • structure-viewer/trunk/assets/js/sv-scripts.js

    r3286634 r3289104  
    5656            }
    5757        });
     58
     59        // Export structure as text file
     60        $('.sv-container').on('click', '.sv-export', function(e) {
     61            e.preventDefault();
     62            var $button = $(this);
     63            var item = $button.data('item');
     64            var type = $button.data('type');
     65
     66            $.ajax({
     67                url: ajaxurl,
     68                type: 'POST',
     69                data: {
     70                    action: 'structureviewer_export',
     71                    nonce: structureviewerSettings.nonce,
     72                    item: item,
     73                    type: type
     74                },
     75                success: function(response) {
     76                    if (response.success) {
     77                        var blob = new Blob([response.data.data], { type: 'text/plain' });
     78                        var url = window.URL.createObjectURL(blob);
     79                        var a = document.createElement('a');
     80                        a.href = url;
     81                        a.download = response.data.filename;
     82                        document.body.appendChild(a);
     83                        a.click();
     84                        window.URL.revokeObjectURL(url);
     85                        a.remove();
     86                    } else {
     87                        alert('Export failed: ' + response.data);
     88                    }
     89                },
     90                error: function() {
     91                    alert('Export failed: Server error.');
     92                }
     93            });
     94        });
    5895    });
    5996})(jQuery);
  • structure-viewer/trunk/includes/admin.php

    r3286634 r3289104  
    1919// Render the admin page
    2020function structureviewer_admin_page() {
    21     // Check user capabilities
    2221    if (!current_user_can('manage_options')) {
    2322        wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'structure-viewer'));
    2423    }
    2524
    26     // Add nonce verification for form
    2725    if (!isset($_GET['sv_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['sv_nonce'])), 'sv_form_action')) {
    28         $type = 'plugin'; // Default to plugin if nonce fails
     26        $type = 'plugin';
    2927        $item = '';
    3028    } else {
    31         // Sanitize GET parameters
    3229        $type = isset($_GET['psv_type']) ? sanitize_text_field(wp_unslash($_GET['psv_type'])) : 'plugin';
    3330        $item = isset($_GET['psv_item']) ? sanitize_text_field(wp_unslash($_GET['psv_item'])) : '';
    3431    }
    3532
    36     // Validate type
    3733    if (!in_array($type, ['plugin', 'theme'], true)) {
    38         $type = 'plugin'; // Default to plugin if invalid
     34        $type = 'plugin';
    3935    }
    4036    ?>
     
    8682            jQuery(document).ready(function($) {
    8783                $('#sv-type').on('change', function() {
    88                     $('#sv-item').val(''); // Reset item selection
    89                     this.form.submit(); // Submit form to reload page
     84                    $('#sv-item').val('');
     85                    this.form.submit();
    9086                });
    9187            });
     
    9591    <?php
    9692}
    97 ?>
  • structure-viewer/trunk/includes/scanner.php

    r3286634 r3289104  
    1717    if ($selected_item) {
    1818        $item_path = realpath($items_dir . '/' . $selected_item);
    19         // Ensure the path is within the allowed directory
    2019        if ($item_path === false || strpos($item_path, realpath($items_dir)) !== 0 || !is_dir($item_path)) {
    2120            echo '<p>' . esc_html__('No plugins or themes found or invalid selection.', 'structure-viewer') . '</p>';
     
    4241        $tree_class = $selected_item ? 'sv-tree-' . esc_attr(sanitize_html_class($item_folder)) : '';
    4342        $heading_class = $selected_item ? 'sv-plugin-heading' : '';
    44        
     43
    4544        if ($selected_item) {
    4645            echo '<div class="sv-plugin-heading">';
     
    4847            echo '<div class="sv-controls" data-tree-class="' . esc_attr($tree_class) . '">';
    4948            echo '<button class="button sv-expand-all">' . esc_html__('Expand All', 'structure-viewer') . '</button> ';
    50             echo '<button class="button sv-collapse-all">' . esc_html__('Collapse', 'structure-viewer') . '</button>';
     49            echo '<button class="button sv-collapse-all">' . esc_html__('Collapse', 'structure-viewer') . '</button> ';
     50            echo '<button class="button sv-export" data-item="' . esc_attr($item_folder) . '" data-type="' . esc_attr($type) . '">' . esc_html__('Export', 'structure-viewer') . '</button>';
    5151            echo '</div>';
    5252            echo '</div>';
     
    5454            echo '<h1 class="' . esc_attr($heading_class) . '">' . esc_html($item_name) . ' (' . ($type === 'plugin' ? esc_html__('Plugin', 'structure-viewer') : esc_html__('Theme', 'structure-viewer')) . ')</h1>';
    5555        }
    56        
     56
    5757        echo '<ul class="sv-tree' . ($tree_class ? ' ' . esc_attr($tree_class) : '') . '">';
    5858        structureviewer_scan_directory($item_path, $item_path, 0, $item_folder, $type);
     
    6262}
    6363
     64// Function to build structure as a text string mimicking the tree view
     65function structureviewer_build_structure_text($base_path, $current_path, $depth = 0, $item_folder = '', $type = 'plugin') {
     66    $base_path = realpath($base_path);
     67    $current_path = realpath($current_path);
     68    if ($base_path === false || $current_path === false || strpos($current_path, $base_path) !== 0) {
     69        return '';
     70    }
     71
     72    $items = glob($current_path . '/*');
     73    if (empty($items)) {
     74        return '';
     75    }
     76
     77    $structure = '';
     78    $folders = [];
     79    $files = [];
     80    foreach ($items as $item) {
     81        if (is_dir($item)) {
     82            $folders[] = $item;
     83        } else {
     84            $files[] = $item;
     85        }
     86    }
     87
     88    sort($folders);
     89    sort($files);
     90    $items = array_merge($folders, $files);
     91
     92    foreach ($items as $item) {
     93        $item = realpath($item);
     94        if ($item === false || strpos($item, $base_path) !== 0) {
     95            continue;
     96        }
     97
     98        $item_name = basename($item);
     99        $is_dir = is_dir($item);
     100
     101        // Add indentation and prefix
     102        $indent = str_repeat('  ', $depth);
     103        $prefix = $depth > 0 ? '- ' : '';
     104        $structure .= $indent . $prefix . $item_name . "\n";
     105
     106        if ($is_dir) {
     107            $structure .= structureviewer_build_structure_text($base_path, $item, $depth + 1, $item_folder, $type);
     108        }
     109    }
     110
     111    return $structure;
     112}
     113
     114// AJAX handler for exporting structure as text
     115add_action('wp_ajax_structureviewer_export', 'structureviewer_export_structure');
     116function structureviewer_export_structure() {
     117    check_ajax_referer(STRUCTUREVIEWER_NONCE, 'nonce');
     118
     119    $type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : 'plugin';
     120    $item = isset($_POST['item']) ? structureviewer_sanitize_item_name($_POST['item']) : '';
     121
     122    if (!in_array($type, ['plugin', 'theme'], true) || empty($item)) {
     123        wp_send_json_error('Invalid parameters.');
     124    }
     125
     126    $items_dir = ($type === 'plugin') ? WP_PLUGIN_DIR : get_theme_root();
     127    $item_path = realpath($items_dir . '/' . $item);
     128
     129    if ($item_path === false || strpos($item_path, realpath($items_dir)) !== 0 || !is_dir($item_path)) {
     130        wp_send_json_error('Invalid item path.');
     131    }
     132
     133    $item_data_list = ($type === 'plugin') ? structureviewer_get_plugin_data_list([$item_path]) : structureviewer_get_theme_data_list([$item_path]);
     134    $item_folder = basename($item_path);
     135    $item_name = isset($item_data_list[$item_folder]['Name']) ? $item_data_list[$item_folder]['Name'] : $item_folder;
     136
     137    // Build the text structure
     138    $structure_text = $item_name . ' (' . ($type === 'plugin' ? 'Plugin' : 'Theme') . ")\n";
     139    $structure_text .= structureviewer_build_structure_text($item_path, $item_path, 0, $item_folder, $type);
     140
     141    wp_send_json_success([
     142        'filename' => 'structure-' . sanitize_file_name($item_name) . '.txt',
     143        'data' => $structure_text
     144    ]);
     145}
     146
    64147// Recursively scan directory and display structure
    65148function structureviewer_scan_directory($base_path, $current_path, $depth = 0, $item_folder = '', $type = 'plugin') {
    66     // Validate paths to prevent directory traversal
    67149    $base_path = realpath($base_path);
    68150    $current_path = realpath($current_path);
     
    128210        return '';
    129211    }
    130     // Remove any path separators or relative paths
    131212    $item_name = str_replace(['/', '\\', '..', '.'], '', $item_name);
    132213    return sanitize_text_field($item_name);
  • structure-viewer/trunk/readme.txt

    r3286634 r3289104  
    44Requires at least: 5.0
    55Tested up to: 6.8.1
    6 Stable tag: 1.0
     6Stable tag: 1.1
    77Requires PHP: 7.0
    88License: GPLv2 or later
     
    1515== Description ==
    1616
    17 Structure Viewer is a lightweight developer tool for WordPress that lets you explore the file and folder structure of installed plugins and themes directly from the admin dashboard. Featuring an intuitive, tree-like view with expandable folders and clickable file links, it’s perfect for developers and site admins looking to debug, audit, or understand the organization of WordPress extensions. Use it to export structures and share with AI tools like Grok or ChatGPT—enabling AI to analyze plugin/theme layouts (e.g., WooCommerce) and assist with precise customizations, such as modifying key files like `includes/class-wc-cart.php`. Secure, optimized, and accessible under Tools > Structure Viewer, this plugin simplifies development workflows. Developed by Blincks.
     17Structure Viewer is a lightweight developer tool for WordPress that lets you explore the file and folder structure of installed plugins and themes directly from the admin dashboard. Featuring an intuitive, tree-like view with expandable folders and clickable file links, it’s perfect for developers and site admins looking to debug, audit, or understand the organization of WordPress extensions. Use it to export structures as a text file and share with AI tools like Grok or ChatGPT—enabling AI to analyze plugin/theme layouts (e.g., WooCommerce) and assist with precise customizations, such as modifying key files like `includes/class-wc-cart.php`. Secure, optimized, and accessible under Tools > Structure Viewer, this plugin simplifies development workflows. Developed by Blincks.
    1818
    1919### Use Cases:
     
    2121- **Learning Plugin Architecture**: Explore the file organization of complex plugins like Elementor to understand their structure, aiding in faster learning and custom development. 
    2222- **Auditing for Security**: Review the file structure of a third-party theme to check for suspicious files or directories, ensuring no malicious code is present. 
    23 - **AI-Assisted Customization**: Export a plugin’s structure (e.g., Yoast SEO) and provide it to an AI tool to analyze files like `includes/class-yoast.php`, enabling tailored modifications such as tweaking SEO metadata handling. 
     23- **AI-Assisted Customization**: Export a plugin’s structure (e.g., Yoast SEO) as a text file and provide it to an AI tool to analyze files like `includes/class-yoast.php`, enabling tailored modifications such as tweaking SEO metadata handling. 
    2424- **Documentation and Collaboration**: Share the folder structure of a custom theme with a team to streamline collaborative development or document its organization for future reference.
    2525
     
    5959Yes, Structure Viewer includes security measures such as input validation, output escaping, directory traversal prevention, and proper capability checks to ensure only authorized users can access the tool.
    6060
     61= How do I export the structure? =
     62When viewing a specific plugin or theme, click the "Export" button to download its structure as a text file, which can be shared or analyzed further.
     63
    6164== Changelog ==
     65
     66= 1.1 =
     67* Added export functionality to download the structure as a text file.
    6268
    6369= 1.0 =
     
    6773== Upgrade Notice ==
    6874
     75= 1.1 =
     76This update adds the ability to export the file structure as a text file, making it easier to share or analyze with other tools.
     77
    6978== Additional Information ==
    7079
  • structure-viewer/trunk/structure-viewer.php

    r3286634 r3289104  
    33Plugin Name: Structure Viewer
    44Description: Displays the file and folder structure of installed WordPress plugins and themes. Developed by Blincks.
    5 Version: 1.0
     5Version: 1.1
    66Author: Blincks
    77Author URI: https://www.blincks.com
     
    3636    $css_version = file_exists($css_path) ? filemtime($css_path) : '2.0';
    3737    wp_enqueue_style(
    38         'structureviewer-styles', // Updated handle with prefix
     38        'structureviewer-styles',
    3939        STRUCTUREVIEWER_PLUGIN_URL . 'assets/css/sv-styles.css',
    4040        [],
     
    4646    $js_version = file_exists($js_path) ? filemtime($js_path) : '2.0';
    4747    wp_enqueue_script(
    48         'structureviewer-scripts', // Updated handle with prefix
     48        'structureviewer-scripts',
    4949        STRUCTUREVIEWER_PLUGIN_URL . 'assets/js/sv-scripts.js',
    5050        ['jquery'],
     
    5353    );
    5454
    55     // Localize script with nonce for potential future AJAX
     55    // Localize script with nonce and AJAX URL for export
    5656    wp_localize_script('structureviewer-scripts', 'structureviewerSettings', [
    57         'nonce' => wp_create_nonce(STRUCTUREVIEWER_NONCE)
     57        'nonce' => wp_create_nonce(STRUCTUREVIEWER_NONCE),
     58        'ajaxurl' => admin_url('admin-ajax.php')
    5859    ]);
    5960}
Note: See TracChangeset for help on using the changeset viewer.