Skip to content

Commit

Permalink
Plugin: add log file downloading (#193)
Browse files Browse the repository at this point in the history
* sketch out fetching logs

* make npm start do a build to make sure the latest is there

* set up wp env to use 8.1 and named plugin and theme paths

* add ui for download logs block

* add dowload handling to the form handler

also stub out the log download data

* allow clicking header to toggle if it has the right className

* make input renderer more general

* update download template and add timestamp defaults

* remove some error logs

* fix how the post title is collected

* refactor the client log endpoint

* clean up log filtering

* remove error log

* fix site size

* add download block to the site template
  • Loading branch information
jhnstn authored Aug 30, 2024
1 parent 324d9d5 commit 682acde
Show file tree
Hide file tree
Showing 14 changed files with 751 additions and 168 deletions.
10 changes: 7 additions & 3 deletions .wp-env.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{
"core": "WordPress/WordPress",
"plugins": [ "./plugin" ],
"themes": [ "./theme" ],
"phpVersion": "8.1",

"config": {
"WP_DEBUG": true,
"WP_DEBUG_LOG": true,
"WP_DEBUG_DISPLAY": true,
"SCRIPT_DEBUG": true,
"WP_DEVELOPMENT_MODE": "all",
"WP_ENVIRONMENT_TYPE": "local"
}
},
"mappings": {
"wp-content/plugins/wpcloud-station-plugin": "./plugin",
"wp-content/themes/wpcloud-station-theme": "./theme"
}
}
2 changes: 1 addition & 1 deletion plugin/blocks/src/components/expanding-section/view.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
((wpcloud) => {
document.querySelectorAll('.wpcloud-block-expanding-section.click-to-toggle').forEach((section) => {
document.querySelectorAll('.wpcloud-block-expanding-section.click-to-toggle, .wp-block-wpcloud-expanding-header.click-to-toggle').forEach((section) => {
section.addEventListener('click', (event) => {
const selection = document.getSelection();
if (selection.type === 'Range') {
Expand Down
81 changes: 48 additions & 33 deletions plugin/blocks/src/components/form-input/render.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,27 @@
return '';
}

$content = apply_filters( 'wpcloud_block_form_render_field_' . $name, $content, $attributes, $block );
$content = apply_filters( 'wpcloud_block_form_render_field', $content, $attributes, $block );
$attributes = apply_filters( 'wpcloud_block_form_field_attributes_' . $name, $attributes, $block );
$content = apply_filters( 'wpcloud_block_form_render_field_' . $name, $content, $attributes, $block );
$content = apply_filters( 'wpcloud_block_form_render_field', $content, $attributes, $block );

$site_mutable_options = WPCloud_Site::get_mutable_options();
// Check block data for values and options.
$current_value = $attributes['value'] ?? '';
$options = array();
$aliases = array();

if ( isset( $attributes['options'] ) ) {

foreach ( $attributes['options'] as $option ) {
$options[ $option['value'] ] = $option['label'];
}
}

// Check mutable options for values and options.
$site_mutable_options = WPCloud_Site::get_mutable_options();
if ( array_key_exists( $name, $site_mutable_options ) ) {
$current_value = WPCLOUD_Site::get_detail( get_the_ID(), $name );
if ( 'ssh_port' === $name ) {
error_log( 'WP Cloud: ' . $current_value );
}

if ( is_wp_error( $current_value ) ) {
error_log( 'WP Cloud: ' . $current_value->get_error_message() );
$current_value = '';
Expand All @@ -42,37 +53,41 @@
}

if ( 'select' === $input_type ) {
$options = $site_mutable_options[ $name ]['options'];
$aliases = $site_mutable_options[ $name ]['option_aliases'] ?? array();
$options_html = '';
if ( ! is_wp_error( $options ) ) {
foreach ( $options as $value => $label ) {

$selected = selected( $current_value, $value, false );
// check for option aliases.
if ( ! $selected && array_key_exists( $value, $aliases ) ) {
$selected = selected( $current_value, $aliases[ $value ], false );
}
$options_html .= sprintf(
'<option value="%s" %s>%s</option>',
esc_attr( $value ),
esc_attr( $selected ),
esc_html( $label )
);
$options = $site_mutable_options[ $name ]['options'] ?? $options;
$aliases = $site_mutable_options[ $name ]['option_aliases'] ?? $aliases;
}
}

if ( 'select' === $input_type ) {
$options_html = '';
if ( ! is_wp_error( $options ) ) {
foreach ( $options as $value => $label ) {

$selected = selected( $current_value, $value, false );
// check for option aliases.
if ( ! $selected && array_key_exists( $value, $aliases ) ) {
$selected = selected( $current_value, $aliases[ $value ], false );
}
$options_html .= sprintf(
'<option value="%s" %s>%s</option>',
esc_attr( $value ),
esc_attr( $selected ),
esc_html( $label )
);
}
}

$regex = '/(<select[^>]*>)(?:\s*<option[^>]*>.*?<\/option>)*\s*(<\/select>)/';
$content = preg_replace( $regex, '$1' . $options_html . '$2', $content );
} else {
$regex = '/(<input .*)\/>/';
if ( 'checkbox' === $input_type ) {
if ( $current_value ) {
$content = preg_replace( $regex, '$1 checked />', $content, 1 );
}
} else {
$content = preg_replace( $regex, '$1 value="' . $current_value . '" />', $content, 1 );
$regex = '/(<select[^>]*>)(?:\s*<option[^>]*>.*?<\/option>)*\s*(<\/select>)/';
$content = preg_replace( $regex, '$1' . $options_html . '$2', $content );
} else {
$regex = '/(<input .*)\/>/';
if ( 'checkbox' === $input_type ) {
if ( $current_value ) {
$content = preg_replace( $regex, '$1 checked />', $content, 1 );
}
} else {
$content = preg_replace( $regex, '$1 value="' . $current_value . '" />', $content, 1 );
}
}

echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
39 changes: 38 additions & 1 deletion plugin/blocks/src/components/form/view.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
((wpcloud) => {

async function saveDownload( response ) {
const blob = await response.blob();
const filename = response.headers.get('Content-Disposition').split('filename=')[1];

if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, filename);
return;
}
const blobURL = window.URL.createObjectURL(blob);
const link = document.createElement('a');

link.style.display = 'none';
link.href = blobURL;
link.setAttribute('download', filename);

if (typeof link.download === 'undefined') {
link.setAttribute('target', '_blank');
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

setTimeout(() => {
window.URL.revokeObjectURL(blobURL);
}, 100);
}

async function submitFormData(form, data) {
form.classList.add('is-loading');
form.classList.remove('is-error');
Expand Down Expand Up @@ -60,7 +87,17 @@
}
);

const result = await response.json();
const contentType = response.headers.get('Content-Type');
let result = {};

if ( contentType.includes('octet-stream')) {
await saveDownload(response);
result.data = { action: 'download' };
} else if ( contentType.includes('json')) {
result = await response.json();
} else {
throw new Error('Invalid response type');
}

wpcloud.hooks.doAction(
'wpcloud_form_response',
Expand Down
17 changes: 17 additions & 0 deletions plugin/blocks/src/log-download/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "wpcloud/log-download",
"version": "0.1.0",
"title": "Download Log File",
"category": "wpcloud",
"icon": "feedback",
"description": "A block to download the log file",
"example": {},
"supports": {
"html": false
},
"textdomain": "wpcloud",
"editorScript": "file:./index.js",
"viewScript": "file:./view.js"
}
71 changes: 71 additions & 0 deletions plugin/blocks/src/log-download/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import metadata from './block.json';
import { inputTemplate } from '../utils/templates';

const required = [
{ name: 'type', label: __('Type'), required: true, hint: '', type: 'select', options: { site: __('Site'), error: __('Error') } },
{ name: 'log_start', label: __('Start Time'),required: true, hint: __( 'Logs are only guaranteed for 28 days. A start date before that may return incomplete data.' ), type: 'datetime' },
{ name: 'log_end', label: __('End Time'), required: true, hint: '', type: 'datetime', value: '2024-08-29T14:40' },
]
const filters = [
{ name: 'page_size', label: __('Page Size'), hint: __('The maximum number of records to retrieve in a single request. Defaults to 500. Max of 10000.'), type: 'number', placeholder: __('Enter page size') },
{ name: 'scroll_id', label: __('Scroll ID'), hint: __( 'String used to specify the next page of data for large queries; the same query arguments as the initial query must be provided with the scroll_id on each subsequent request.' ), type: 'text', placeholder: __('Enter scroll ID') },
{ name: 'sort_order', label: __('Sort Order'), hint: '', type: 'select', options: { asc: __('Ascending'), desc: __('Descending') } },

// error filters
{ name: 'filter-error__severity', label: __('Log Level'), hint: 'Comma separated log levels. Example: User, Warning ,Deprecated, Fatal error', type: 'text', placeholder: __('Enter log level'), className: 'wpcloud_form_input__optional_log_filter'},
// site filters
{ name: 'filter-site__cached', label: __('Cached'), hint: '', type: 'text', className: 'wpcloud_form_input__option_log_filter' } ,
{ name: 'filter-site__renderer', label: __('Renderer'), hint: '', type: 'text', className: 'wpcloud_form_input__optional_log_filter' },
{ name: 'filter-site__request_type', label: __('Request Type'), hint: '', type: 'text', className: 'wpcloud_form_input__optional_log_filter' },
{ name: 'filter-site__status', label: __('Status'), hint: '', type: 'text', placeholder: '200,404', className: 'wpcloud_form_input__optional_log_filter' },
{ name: 'filter-site__user_ip', label: __('User IP'), hint: '', type: 'text', placeholder: __('127.0.0.0'), className: 'wpcloud_form_input__optional_log_filter' },
];

const template = [
[ 'wpcloud/site-details', { metadata: { name: 'Download logs form' } },
[
[ 'core/heading', { level: 2, content: __('Download Logs') } ],
[
'wpcloud/form',
{
ajax: true,
wpcloudAction: 'log_download',
className: 'wpcloud_block_form__log_download',
},
[
...required.map(inputTemplate),
[ 'wpcloud/expanding-section', { metadata: { name: 'Log Filters' }, clickToToggle: false, hideHeader: false },
[
[ 'wpcloud/expanding-header', { className: 'click-to-toggle' },
[
['core/heading', { level: 3, content: __('Filters'), }],
],
],
[ 'wpcloud/expanding-content', {},
[
...filters.map(inputTemplate)
]
],
]
],
[ 'wpcloud/button', { label: __('Download'), type: 'submit' } ],
]
],
]
]
];

registerBlockType(metadata.name, {
edit: () => <InnerBlocks template={template} />,
save: () => <InnerBlocks.Content />,
});
Loading

0 comments on commit 682acde

Please sign in to comment.