Template API: Server-side logging (#41316)
This commit is contained in:
commit
f4596deddb
|
@ -58,4 +58,4 @@ require 'features/features.php';
|
|||
require 'rest-api-filters/class-wca-test-helper-rest-api-filters.php';
|
||||
require 'rest-api-filters/hook.php';
|
||||
require 'live-branches/manifest.php';
|
||||
require 'live-branches/install.php';
|
||||
require 'tools/set-block-template-logging-threshold.php';
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/tools/get-logging-levels/v1',
|
||||
'tools_get_logging_levels',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
)
|
||||
);
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/tools/get-block-template-logging-threshold/v1',
|
||||
'tools_get_block_template_logging_threshold',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
)
|
||||
);
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/tools/update-block-template-logging-threshold/v1',
|
||||
'tools_update_block_template_logging_threshold',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'args' => array(
|
||||
'threshold' => array(
|
||||
'description' => 'Logging threshold',
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the list of logging levels.
|
||||
*/
|
||||
function tools_get_logging_levels() {
|
||||
$levels = array(
|
||||
array(
|
||||
'label' => 'Emergency',
|
||||
'value' => \WC_Log_Levels::EMERGENCY,
|
||||
),
|
||||
array(
|
||||
'label' => 'Alert',
|
||||
'value' => \WC_Log_Levels::ALERT,
|
||||
),
|
||||
array(
|
||||
'label' => 'Critical',
|
||||
'value' => \WC_Log_Levels::CRITICAL,
|
||||
),
|
||||
array(
|
||||
'label' => 'Error',
|
||||
'value' => \WC_Log_Levels::ERROR,
|
||||
),
|
||||
array(
|
||||
'label' => 'Warning',
|
||||
'value' => \WC_Log_Levels::WARNING,
|
||||
),
|
||||
array(
|
||||
'label' => 'Notice',
|
||||
'value' => \WC_Log_Levels::NOTICE,
|
||||
),
|
||||
array(
|
||||
'label' => 'Info',
|
||||
'value' => \WC_Log_Levels::INFO,
|
||||
),
|
||||
array(
|
||||
'label' => 'Debug',
|
||||
'value' => \WC_Log_Levels::DEBUG,
|
||||
),
|
||||
);
|
||||
|
||||
return new WP_REST_Response( $levels, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block template logging threshold.
|
||||
*/
|
||||
function tools_get_block_template_logging_threshold() {
|
||||
$threshold = get_option( 'woocommerce_block_template_logging_threshold', \WC_Log_Levels::WARNING );
|
||||
|
||||
return new WP_REST_Response( $threshold, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the block template logging threshold.
|
||||
*
|
||||
* @param WP_REST_Request $request The full request data.
|
||||
*/
|
||||
function tools_update_block_template_logging_threshold( $request ) {
|
||||
$threshold = $request->get_param( 'threshold' );
|
||||
|
||||
if ( ! isset( $threshold ) || ! \WC_Log_Levels::is_valid_level( $threshold ) ) {
|
||||
return new WP_REST_Response( 'Invalid threshold', 400 );
|
||||
}
|
||||
|
||||
update_option( 'woocommerce_block_template_logging_threshold', $threshold );
|
||||
|
||||
return new WP_REST_Response( $threshold, 200 );
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add ability to update block templates logging threshold.
|
|
@ -91,8 +91,8 @@
|
|||
&.command {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.trigger-cron-job {
|
||||
width: 40%;
|
||||
.select-description {
|
||||
width: 60%;
|
||||
padding-top: 4px;
|
||||
.components-base-control__field {
|
||||
margin-bottom: 0;
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
*/
|
||||
import { TriggerCronJob, TRIGGER_CRON_ACTION_NAME } from './trigger-cron';
|
||||
import { DisableEmail } from './disable-email';
|
||||
import {
|
||||
UpdateBlockTemplateLoggingThreshold,
|
||||
UPDATE_BLOCK_TEMPLATE_LOGGING_THRESHOLD_ACTION_NAME,
|
||||
} from './update-block-template-logging-threshold';
|
||||
import {
|
||||
TriggerUpdateCallbacks,
|
||||
TRIGGER_UPDATE_CALLBACKS_ACTION_NAME,
|
||||
|
@ -69,4 +73,9 @@ export default [
|
|||
description: 'Resets Customize Your Store changes.',
|
||||
action: 'resetCustomizeYourStore',
|
||||
},
|
||||
{
|
||||
command: 'Update block template logging threshold',
|
||||
description: <UpdateBlockTemplateLoggingThreshold />,
|
||||
action: UPDATE_BLOCK_TEMPLATE_LOGGING_THRESHOLD_ACTION_NAME,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -32,7 +32,7 @@ export const TriggerCronJob = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="trigger-cron-job">
|
||||
<div className="select-description">
|
||||
{ ! cronList ? (
|
||||
<p>Loading ...</p>
|
||||
) : (
|
||||
|
|
|
@ -35,7 +35,7 @@ export const TriggerUpdateCallbacks = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="trigger-cron-job">
|
||||
<div className="select-description">
|
||||
{ ! dbUpdateVersions ? (
|
||||
<p>Loading ...</p>
|
||||
) : (
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import { SelectControl } from '@wordpress/components';
|
||||
import { useEffect, useState } from '@wordpress/element';
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore no types
|
||||
// eslint-disable-next-line @woocommerce/dependency-group
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore no types
|
||||
// eslint-disable-next-line @woocommerce/dependency-group
|
||||
import { STORE_KEY } from '../data/constants';
|
||||
|
||||
export const UPDATE_BLOCK_TEMPLATE_LOGGING_THRESHOLD_ACTION_NAME =
|
||||
'updateBlockTemplateLoggingThreshold';
|
||||
|
||||
interface LoggingLevel {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const UpdateBlockTemplateLoggingThreshold = () => {
|
||||
const { loggingLevels, threshold, isLoading } = useSelect(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore no types
|
||||
( select ) => {
|
||||
const { getLoggingLevels, getBlockTemplateLoggingThreshold } =
|
||||
select( STORE_KEY );
|
||||
|
||||
const retrievedLoggingLevels = getLoggingLevels();
|
||||
const retrievedThreshold = getBlockTemplateLoggingThreshold();
|
||||
|
||||
return {
|
||||
loggingLevels: retrievedLoggingLevels,
|
||||
threshold: retrievedThreshold,
|
||||
isLoading: ! retrievedLoggingLevels || ! retrievedThreshold,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const [ newThreshold, setNewThreshold ] = useState( threshold );
|
||||
|
||||
const { updateCommandParams } = useDispatch( STORE_KEY );
|
||||
|
||||
function onThresholdChange( selectedThreshold: string ) {
|
||||
setNewThreshold( selectedThreshold );
|
||||
updateCommandParams(
|
||||
UPDATE_BLOCK_TEMPLATE_LOGGING_THRESHOLD_ACTION_NAME,
|
||||
{
|
||||
threshold: selectedThreshold,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getOptions() {
|
||||
return loggingLevels.map( ( loggingLevel: LoggingLevel ) => {
|
||||
return {
|
||||
label: loggingLevel.label,
|
||||
value: loggingLevel.value,
|
||||
};
|
||||
} );
|
||||
}
|
||||
|
||||
useEffect( () => {
|
||||
setNewThreshold( threshold );
|
||||
}, [ threshold ] );
|
||||
|
||||
return (
|
||||
<div className="select-description">
|
||||
{ isLoading ? (
|
||||
<p>Loading...</p>
|
||||
) : (
|
||||
<SelectControl
|
||||
label="Threshold"
|
||||
onChange={ onThresholdChange }
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore labelPosition prop exists
|
||||
labelPosition="side"
|
||||
options={ getOptions() }
|
||||
value={ newThreshold }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -8,6 +8,11 @@ const TYPES = {
|
|||
SET_CRON_JOBS: 'SET_CRON_JOBS',
|
||||
IS_EMAIL_DISABLED: 'IS_EMAIL_DISABLED',
|
||||
SET_DB_UPDATE_VERSIONS: 'SET_DB_UPDATE_VERSIONS',
|
||||
SET_LOGGING_LEVELS: 'SET_LOGGING_LEVELS',
|
||||
SET_BLOCK_TEMPLATE_LOGGING_THRESHOLD:
|
||||
'SET_BLOCK_TEMPLATE_LOGGING_THRESHOLD',
|
||||
UPDATE_BLOCK_TEMPLATE_LOGGING_THRESHOLD:
|
||||
'UPDATE_BLOCK_TEMPLATE_LOGGING_THRESHOLD',
|
||||
};
|
||||
|
||||
export default TYPES;
|
||||
|
|
|
@ -229,3 +229,31 @@ export function* resetCustomizeYourStore() {
|
|||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
export function setLoggingLevels( loggingLevels ) {
|
||||
return {
|
||||
type: TYPES.SET_LOGGING_LEVELS,
|
||||
loggingLevels,
|
||||
};
|
||||
}
|
||||
|
||||
export function setBlockTemplateLoggingThreshold(
|
||||
blockTemplateLoggingThreshold
|
||||
) {
|
||||
return {
|
||||
type: TYPES.SET_BLOCK_TEMPLATE_LOGGING_THRESHOLD,
|
||||
blockTemplateLoggingThreshold,
|
||||
};
|
||||
}
|
||||
|
||||
export function* updateBlockTemplateLoggingThreshold( params ) {
|
||||
yield runCommand( 'Update block template logging threshold', function* () {
|
||||
yield apiFetch( {
|
||||
path:
|
||||
API_NAMESPACE +
|
||||
'/tools/update-block-template-logging-threshold/v1',
|
||||
method: 'POST',
|
||||
data: params,
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ const DEFAULT_STATE = {
|
|||
params: [],
|
||||
status: '',
|
||||
dbUpdateVersions: [],
|
||||
loggingLevels: null,
|
||||
blockTemplateLoggingThreshold: null,
|
||||
};
|
||||
|
||||
const reducer = ( state = DEFAULT_STATE, action ) => {
|
||||
|
@ -80,6 +82,17 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
|
|||
...state,
|
||||
dbUpdateVersions: action.versions,
|
||||
};
|
||||
case TYPES.SET_LOGGING_LEVELS:
|
||||
return {
|
||||
...state,
|
||||
loggingLevels: action.loggingLevels,
|
||||
};
|
||||
case TYPES.SET_BLOCK_TEMPLATE_LOGGING_THRESHOLD:
|
||||
return {
|
||||
...state,
|
||||
blockTemplateLoggingThreshold:
|
||||
action.blockTemplateLoggingThreshold,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,11 @@ import { apiFetch } from '@wordpress/data-controls';
|
|||
*/
|
||||
import { API_NAMESPACE } from './constants';
|
||||
import {
|
||||
setBlockTemplateLoggingThreshold,
|
||||
setCronJobs,
|
||||
setDBUpdateVersions,
|
||||
setIsEmailDisabled,
|
||||
setLoggingLevels,
|
||||
} from './actions';
|
||||
|
||||
export function* getCronJobs() {
|
||||
|
@ -55,3 +57,31 @@ export function* getIsEmailDisabled() {
|
|||
throw new Error( error );
|
||||
}
|
||||
}
|
||||
|
||||
export function* getLoggingLevels() {
|
||||
const path = `${ API_NAMESPACE }/tools/get-logging-levels/v1`;
|
||||
|
||||
try {
|
||||
const response = yield apiFetch( {
|
||||
path,
|
||||
method: 'GET',
|
||||
} );
|
||||
yield setLoggingLevels( response );
|
||||
} catch ( error ) {
|
||||
throw new Error( error );
|
||||
}
|
||||
}
|
||||
|
||||
export function* getBlockTemplateLoggingThreshold() {
|
||||
const path = `${ API_NAMESPACE }/tools/get-block-template-logging-threshold/v1`;
|
||||
|
||||
try {
|
||||
const response = yield apiFetch( {
|
||||
path,
|
||||
method: 'GET',
|
||||
} );
|
||||
yield setBlockTemplateLoggingThreshold( response );
|
||||
} catch ( error ) {
|
||||
throw new Error( error );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,3 +25,11 @@ export function getIsEmailDisabled( state ) {
|
|||
export function getDBUpdateVersions( state ) {
|
||||
return state.dbUpdateVersions;
|
||||
}
|
||||
|
||||
export function getLoggingLevels( state ) {
|
||||
return state.loggingLevels;
|
||||
}
|
||||
|
||||
export function getBlockTemplateLoggingThreshold( state ) {
|
||||
return state.blockTemplateLoggingThreshold;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Improve block template API logging.
|
|
@ -10,6 +10,8 @@ use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTem
|
|||
use Automattic\WooCommerce\Internal\Admin\Features\ProductBlockEditor\ProductTemplates\ProductVariationTemplate;
|
||||
use Automattic\WooCommerce\Admin\PageController;
|
||||
use Automattic\WooCommerce\Internal\Admin\BlockTemplateRegistry\BlockTemplateRegistry;
|
||||
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\Block;
|
||||
use Automattic\WooCommerce\Internal\Admin\BlockTemplates\BlockTemplateLogger;
|
||||
use WP_Block_Editor_Context;
|
||||
|
||||
/**
|
||||
|
@ -62,6 +64,9 @@ class Init {
|
|||
|
||||
$tracks = new Tracks();
|
||||
$tracks->init();
|
||||
|
||||
// Make sure the block template logger is initialized before any templates are created.
|
||||
BlockTemplateLogger::get_instance();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,13 +204,22 @@ class Init {
|
|||
private function get_product_editor_settings() {
|
||||
$editor_settings = array();
|
||||
|
||||
$template_registry = wc_get_container()->get( BlockTemplateRegistry::class );
|
||||
$template_registry = wc_get_container()->get( BlockTemplateRegistry::class );
|
||||
$block_template_logger = BlockTemplateLogger::get_instance();
|
||||
|
||||
$block_template_logger->log_template_events_to_file( 'simple-product' );
|
||||
$block_template_logger->log_template_events_to_file( 'product-variation' );
|
||||
|
||||
$editor_settings['templates'] = array(
|
||||
'product' => $template_registry->get_registered( 'simple-product' )->get_formatted_template(),
|
||||
'product_variation' => $template_registry->get_registered( 'product-variation' )->get_formatted_template(),
|
||||
);
|
||||
|
||||
$editor_settings['templateEvents'] = array(
|
||||
'product' => $block_template_logger->get_formatted_template_events( 'simple-product' ),
|
||||
'product_variation' => $block_template_logger->get_formatted_template_events( 'product-variation' ),
|
||||
);
|
||||
|
||||
$block_editor_context = new WP_Block_Editor_Context( array( 'name' => self::EDITOR_CONTEXT_NAME ) );
|
||||
|
||||
return get_block_editor_settings( $editor_settings, $block_editor_context );
|
||||
|
|
|
@ -252,6 +252,15 @@ class AbstractBlock implements BlockInterface {
|
|||
'expression' => $expression,
|
||||
);
|
||||
|
||||
/**
|
||||
* Action called after a hide condition is added to a block.
|
||||
*
|
||||
* @param BlockInterface $block The block.
|
||||
*
|
||||
* @since 8.4.0
|
||||
*/
|
||||
do_action( 'woocommerce_block_template_after_add_hide_condition', $this );
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
|
@ -262,6 +271,15 @@ class AbstractBlock implements BlockInterface {
|
|||
*/
|
||||
public function remove_hide_condition( string $key ) {
|
||||
unset( $this->hide_conditions[ $key ] );
|
||||
|
||||
/**
|
||||
* Action called after a hide condition is removed from a block.
|
||||
*
|
||||
* @param BlockInterface $block The block.
|
||||
*
|
||||
* @since 8.4.0
|
||||
*/
|
||||
do_action( 'woocommerce_block_template_after_remove_hide_condition', $this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,7 +18,7 @@ trait BlockContainerTrait {
|
|||
*
|
||||
* @var BlockInterface[]
|
||||
*/
|
||||
private $inner_blocks = [];
|
||||
private $inner_blocks = array();
|
||||
|
||||
// phpcs doesn't take into account exceptions thrown by called methods.
|
||||
// phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
||||
|
@ -43,16 +43,7 @@ trait BlockContainerTrait {
|
|||
}
|
||||
|
||||
$is_detached = method_exists( $this, 'is_detached' ) && $this->is_detached();
|
||||
if ( $is_detached ) {
|
||||
BlockTemplateLogger::get_instance()->warning(
|
||||
'Block added to detached container. Block will not be included in the template, since the container will not be included in the template.',
|
||||
[
|
||||
'block' => $block,
|
||||
'container' => $this,
|
||||
'template' => $this->get_root_template(),
|
||||
]
|
||||
);
|
||||
} else {
|
||||
if ( ! $is_detached ) {
|
||||
$this->get_root_template()->cache_block( $block );
|
||||
}
|
||||
|
||||
|
@ -169,14 +160,6 @@ trait BlockContainerTrait {
|
|||
}
|
||||
);
|
||||
|
||||
BlockTemplateLogger::get_instance()->info(
|
||||
'Block removed from template.',
|
||||
[
|
||||
'block' => $block,
|
||||
'template' => $root_template,
|
||||
]
|
||||
);
|
||||
|
||||
$this->do_after_remove_block_action( $block );
|
||||
$this->do_after_remove_specific_block_action( $block );
|
||||
}
|
||||
|
@ -237,12 +220,7 @@ trait BlockContainerTrait {
|
|||
*/
|
||||
do_action( 'woocommerce_block_template_after_add_block', $block );
|
||||
} catch ( \Exception $e ) {
|
||||
$this->handle_exception_doing_action(
|
||||
'Error after adding block to template.',
|
||||
'woocommerce_block_template_after_add_block',
|
||||
$block,
|
||||
$e
|
||||
);
|
||||
$this->do_after_add_block_error_action( $block, 'woocommerce_block_template_after_add_block', $e );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,15 +244,35 @@ trait BlockContainerTrait {
|
|||
*/
|
||||
do_action( "woocommerce_block_template_area_{$this->get_root_template()->get_area()}_after_add_block_{$block->get_id()}", $block );
|
||||
} catch ( \Exception $e ) {
|
||||
$this->handle_exception_doing_action(
|
||||
'Error after adding block to template.',
|
||||
"woocommerce_block_template_area_{$this->get_root_template()->get_area()}_after_add_block_{$block->get_id()}",
|
||||
$block,
|
||||
$e
|
||||
);
|
||||
$this->do_after_add_block_error_action( $block, "woocommerce_block_template_area_{$this->get_root_template()->get_area()}_after_add_block_{$block->get_id()}", $e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the `woocommerce_block_after_add_block_error` action.
|
||||
*
|
||||
* @param BlockInterface $block The block.
|
||||
* @param string $action The action that threw the exception.
|
||||
* @param \Exception $e The exception.
|
||||
*/
|
||||
private function do_after_add_block_error_action( BlockInterface $block, string $action, \Exception $e ) {
|
||||
/**
|
||||
* Action called after an exception is thrown by a `woocommerce_block_template_after_add_block` action hook.
|
||||
*
|
||||
* @param BlockInterface $block The block.
|
||||
* @param string $action The action that threw the exception.
|
||||
* @param \Exception $exception The exception.
|
||||
*
|
||||
* @since 8.4.0
|
||||
*/
|
||||
do_action(
|
||||
'woocommerce_block_template_after_add_block_error',
|
||||
$block,
|
||||
$action,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the `woocommerce_block_template_after_remove_block` action.
|
||||
* Handle exceptions thrown by the action.
|
||||
|
@ -295,12 +293,7 @@ trait BlockContainerTrait {
|
|||
*/
|
||||
do_action( 'woocommerce_block_template_after_remove_block', $block );
|
||||
} catch ( \Exception $e ) {
|
||||
$this->handle_exception_doing_action(
|
||||
'Error after removing block from template.',
|
||||
'woocommerce_block_template_after_remove_block',
|
||||
$block,
|
||||
$e
|
||||
);
|
||||
$this->do_after_remove_block_error_action( $block, 'woocommerce_block_template_after_remove_block', $e );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,33 +317,32 @@ trait BlockContainerTrait {
|
|||
*/
|
||||
do_action( "woocommerce_block_template_area_{$this->get_root_template()->get_area()}_after_remove_block_{$block->get_id()}", $block );
|
||||
} catch ( \Exception $e ) {
|
||||
$this->handle_exception_doing_action(
|
||||
'Error after removing block from template.',
|
||||
"woocommerce_block_template_area_{$this->get_root_template()->get_area()}_after_remove_block_{$block->get_id()}",
|
||||
$block,
|
||||
$e
|
||||
);
|
||||
$this->do_after_remove_block_error_action( $block, "woocommerce_block_template_area_{$this->get_root_template()->get_area()}_after_remove_block_{$block->get_id()}", $e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception thrown by an action.
|
||||
* Do the `woocommerce_block_after_remove_block_error` action.
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param string $action_tag The action tag.
|
||||
* @param BlockInterface $block The block.
|
||||
* @param \Exception $e The exception.
|
||||
* @param BlockInterface $block The block.
|
||||
* @param string $action The action that threw the exception.
|
||||
* @param \Exception $e The exception.
|
||||
*/
|
||||
private function handle_exception_doing_action( string $message, string $action_tag, BlockInterface $block, \Exception $e ) {
|
||||
BlockTemplateLogger::get_instance()->error(
|
||||
$message,
|
||||
[
|
||||
'exception' => $e,
|
||||
'action' => $action_tag,
|
||||
'container' => $this,
|
||||
'block' => $block,
|
||||
'template' => $this->get_root_template(),
|
||||
],
|
||||
private function do_after_remove_block_error_action( BlockInterface $block, string $action, \Exception $e ) {
|
||||
/**
|
||||
* Action called after an exception is thrown by a `woocommerce_block_template_after_remove_block` action hook.
|
||||
*
|
||||
* @param BlockInterface $block The block.
|
||||
* @param string $action The action that threw the exception.
|
||||
* @param \Exception $exception The exception.
|
||||
*
|
||||
* @since 8.4.0
|
||||
*/
|
||||
do_action(
|
||||
'woocommerce_block_template_after_remove_block_error',
|
||||
$block,
|
||||
$action,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,68 @@ namespace Automattic\WooCommerce\Internal\Admin\BlockTemplates;
|
|||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockContainerInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\BlockTemplateInterface;
|
||||
use Automattic\WooCommerce\Admin\BlockTemplates\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Logger for block template modifications.
|
||||
*/
|
||||
class BlockTemplateLogger {
|
||||
const BLOCK_ADDED = 'block_added';
|
||||
const BLOCK_REMOVED = 'block_removed';
|
||||
const BLOCK_MODIFIED = 'block_modified';
|
||||
const BLOCK_ADDED_TO_DETACHED_CONTAINER = 'block_added_to_detached_container';
|
||||
const HIDE_CONDITION_ADDED = 'hide_condition_added';
|
||||
const HIDE_CONDITION_REMOVED = 'hide_condition_removed';
|
||||
const HIDE_CONDITION_ADDED_TO_DETACHED_BLOCK = 'hide_condition_added_to_detached_block';
|
||||
const ERROR_AFTER_BLOCK_ADDED = 'error_after_block_added';
|
||||
const ERROR_AFTER_BLOCK_REMOVED = 'error_after_block_removed';
|
||||
|
||||
const LOG_HASH_TRANSIENT_BASE_NAME = 'wc_block_template_events_log_hash_';
|
||||
|
||||
/**
|
||||
* Event types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $event_types = array(
|
||||
self::BLOCK_ADDED => array(
|
||||
'level' => \WC_Log_Levels::DEBUG,
|
||||
'message' => 'Block added to template.',
|
||||
),
|
||||
self::BLOCK_REMOVED => array(
|
||||
'level' => \WC_Log_Levels::NOTICE,
|
||||
'message' => 'Block removed from template.',
|
||||
),
|
||||
self::BLOCK_MODIFIED => array(
|
||||
'level' => \WC_Log_Levels::NOTICE,
|
||||
'message' => 'Block modified in template.',
|
||||
),
|
||||
self::BLOCK_ADDED_TO_DETACHED_CONTAINER => array(
|
||||
'level' => \WC_Log_Levels::WARNING,
|
||||
'message' => 'Block added to detached container. Block will not be included in the template, since the container will not be included in the template.',
|
||||
),
|
||||
self::HIDE_CONDITION_ADDED => array(
|
||||
'level' => \WC_Log_Levels::NOTICE,
|
||||
'message' => 'Hide condition added to block.',
|
||||
),
|
||||
self::HIDE_CONDITION_REMOVED => array(
|
||||
'level' => \WC_Log_Levels::NOTICE,
|
||||
'message' => 'Hide condition removed from block.',
|
||||
),
|
||||
self::HIDE_CONDITION_ADDED_TO_DETACHED_BLOCK => array(
|
||||
'level' => \WC_Log_Levels::WARNING,
|
||||
'message' => 'Hide condition added to detached block. Block will not be included in the template, so the hide condition is not needed.',
|
||||
),
|
||||
self::ERROR_AFTER_BLOCK_ADDED => array(
|
||||
'level' => \WC_Log_Levels::WARNING,
|
||||
'message' => 'Error after block added to template.',
|
||||
),
|
||||
self::ERROR_AFTER_BLOCK_REMOVED => array(
|
||||
'level' => \WC_Log_Levels::WARNING,
|
||||
'message' => 'Error after block removed from template.',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Singleton instance.
|
||||
*
|
||||
|
@ -24,6 +81,27 @@ class BlockTemplateLogger {
|
|||
*/
|
||||
protected $logger = null;
|
||||
|
||||
/**
|
||||
* All template events.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $all_template_events = array();
|
||||
|
||||
/**
|
||||
* Templates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $templates = array();
|
||||
|
||||
/**
|
||||
* Threshold severity.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $threshold_severity = null;
|
||||
|
||||
/**
|
||||
* Get the singleton instance.
|
||||
*/
|
||||
|
@ -40,44 +118,283 @@ class BlockTemplateLogger {
|
|||
*/
|
||||
protected function __construct() {
|
||||
$this->logger = wc_get_logger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an informational message.
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param array $info Additional info to log.
|
||||
*/
|
||||
public function info( string $message, array $info = [] ) {
|
||||
$this->logger->info(
|
||||
$this->format_message( $message, $info ),
|
||||
[ 'source' => 'block_template' ]
|
||||
$threshold = get_option( 'woocommerce_block_template_logging_threshold', \WC_Log_Levels::WARNING );
|
||||
if ( ! \WC_Log_Levels::is_valid_level( $threshold ) ) {
|
||||
$threshold = \WC_Log_Levels::INFO;
|
||||
}
|
||||
|
||||
$this->threshold_severity = \WC_Log_Levels::get_level_severity( $threshold );
|
||||
|
||||
add_action(
|
||||
'woocommerce_block_template_after_add_block',
|
||||
function ( BlockInterface $block ) {
|
||||
$is_detached = method_exists( $block->get_parent(), 'is_detached' ) && $block->get_parent()->is_detached();
|
||||
|
||||
$this->log(
|
||||
$is_detached
|
||||
? $this::BLOCK_ADDED_TO_DETACHED_CONTAINER
|
||||
: $this::BLOCK_ADDED,
|
||||
$block,
|
||||
);
|
||||
},
|
||||
0,
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_block_template_after_remove_block',
|
||||
function ( BlockInterface $block ) {
|
||||
$this->log(
|
||||
$this::BLOCK_REMOVED,
|
||||
$block,
|
||||
);
|
||||
},
|
||||
0,
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_block_template_after_add_hide_condition',
|
||||
function ( BlockInterface $block ) {
|
||||
$this->log(
|
||||
$block->is_detached()
|
||||
? $this::HIDE_CONDITION_ADDED_TO_DETACHED_BLOCK
|
||||
: $this::HIDE_CONDITION_ADDED,
|
||||
$block,
|
||||
);
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_block_template_after_remove_hide_condition',
|
||||
function ( BlockInterface $block ) {
|
||||
$this->log(
|
||||
$this::HIDE_CONDITION_REMOVED,
|
||||
$block,
|
||||
);
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_block_template_after_add_block_error',
|
||||
function ( BlockInterface $block, string $action, \Exception $exception ) {
|
||||
$this->log(
|
||||
$this::ERROR_AFTER_BLOCK_ADDED,
|
||||
$block,
|
||||
array(
|
||||
'action' => $action,
|
||||
'exception' => $exception,
|
||||
),
|
||||
);
|
||||
},
|
||||
0,
|
||||
3
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_block_template_after_remove_block_error',
|
||||
function ( BlockInterface $block, string $action, \Exception $exception ) {
|
||||
$this->log(
|
||||
$this::ERROR_AFTER_BLOCK_REMOVED,
|
||||
$block,
|
||||
array(
|
||||
'action' => $action,
|
||||
'exception' => $exception,
|
||||
),
|
||||
);
|
||||
},
|
||||
0,
|
||||
3
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a warning message.
|
||||
* Get all template events for a given template.
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param array $info Additional info to log.
|
||||
* @param string $template_id Template ID.
|
||||
*/
|
||||
public function warning( string $message, array $info = [] ) {
|
||||
$this->logger->warning(
|
||||
$this->format_message( $message, $info ),
|
||||
[ 'source' => 'block_template' ]
|
||||
);
|
||||
public function get_formatted_template_events( string $template_id ): array {
|
||||
if ( ! isset( $this->all_template_events[ $template_id ] ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$template_events = $this->all_template_events[ $template_id ];
|
||||
$template = $this->templates[ $template_id ];
|
||||
|
||||
$formatted_template_events = array();
|
||||
|
||||
foreach ( $template_events as $template_event ) {
|
||||
$container = $template_event['container'];
|
||||
$block = $template_event['block'];
|
||||
|
||||
$formatted_template_events[] = array(
|
||||
'level' => $template_event['level'],
|
||||
'event_type' => $template_event['event_type'],
|
||||
'message' => $template_event['message'],
|
||||
'container' => $container instanceof BlockInterface
|
||||
? array(
|
||||
'id' => $container->get_id(),
|
||||
'name' => $container->get_name(),
|
||||
)
|
||||
: null,
|
||||
'block' => array(
|
||||
'id' => $block->get_id(),
|
||||
'name' => $block->get_name(),
|
||||
),
|
||||
'additional_info' => $this->format_info( $template_event['additional_info'] ),
|
||||
);
|
||||
}
|
||||
|
||||
return $formatted_template_events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an error message.
|
||||
* Log all template events for a given template to the log file.
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param array $info Additional info to log.
|
||||
* @param string $template_id Template ID.
|
||||
*/
|
||||
public function error( string $message, array $info = [] ) {
|
||||
$this->logger->error(
|
||||
$this->format_message( $message, $info ),
|
||||
[ 'source' => 'block_template' ]
|
||||
public function log_template_events_to_file( string $template_id ) {
|
||||
if ( ! isset( $this->all_template_events[ $template_id ] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$template_events = $this->all_template_events[ $template_id ];
|
||||
|
||||
$hash = $this->generate_template_events_hash( $template_events );
|
||||
|
||||
if ( ! $this->has_template_events_changed( $template_id, $hash ) ) {
|
||||
// Nothing has changed since the last time this was logged,
|
||||
// so don't log it again.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->set_template_events_log_hash( $template_id, $hash );
|
||||
|
||||
$template = $this->templates[ $template_id ];
|
||||
|
||||
foreach ( $template_events as $template_event ) {
|
||||
$info = array_merge(
|
||||
array(
|
||||
'template' => $template,
|
||||
'container' => $template_event['container'],
|
||||
'block' => $template_event['block'],
|
||||
),
|
||||
$template_event['additional_info']
|
||||
);
|
||||
|
||||
$message = $this->format_message( $template_event['message'], $info );
|
||||
|
||||
$this->logger->log(
|
||||
$template_event['level'],
|
||||
$message,
|
||||
array( 'source' => 'block_template' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the template events changed since the last time they were logged?
|
||||
*
|
||||
* @param string $template_id Template ID.
|
||||
* @param string $events_hash Events hash.
|
||||
*/
|
||||
private function has_template_events_changed( string $template_id, string $events_hash ) {
|
||||
$previous_hash = get_transient( self::LOG_HASH_TRANSIENT_BASE_NAME . $template_id );
|
||||
|
||||
return $previous_hash !== $events_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a hash for a given set of template events.
|
||||
*
|
||||
* @param array $template_events Template events.
|
||||
*/
|
||||
private function generate_template_events_hash( array $template_events ): string {
|
||||
return md5( wp_json_encode( $template_events ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the template events hash for a given template.
|
||||
*
|
||||
* @param string $template_id Template ID.
|
||||
* @param string $hash Hash of template events.
|
||||
*/
|
||||
private function set_template_events_log_hash( string $template_id, string $hash ) {
|
||||
set_transient( self::LOG_HASH_TRANSIENT_BASE_NAME . $template_id, $hash );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an event.
|
||||
*
|
||||
* @param string $event_type Event type.
|
||||
* @param BlockInterface $block Block.
|
||||
* @param array $additional_info Additional info.
|
||||
*/
|
||||
private function log( string $event_type, BlockInterface $block, $additional_info = array() ) {
|
||||
if ( ! isset( self::$event_types[ $event_type ] ) ) {
|
||||
/* translators: 1: WC_Logger::log 2: level */
|
||||
wc_doing_it_wrong( __METHOD__, sprintf( __( '%1$s was called with an invalid event type "%2$s".', 'woocommerce' ), '<code>BlockTemplateLogger::log</code>', $event_type ), '8.4' );
|
||||
}
|
||||
|
||||
$event_type_info = isset( self::$event_types[ $event_type ] )
|
||||
? array_merge(
|
||||
self::$event_types[ $event_type ],
|
||||
array(
|
||||
'event_type' => $event_type,
|
||||
)
|
||||
)
|
||||
: array(
|
||||
'level' => \WC_Log_Levels::ERROR,
|
||||
'event_type' => $event_type,
|
||||
'message' => 'Unknown error.',
|
||||
);
|
||||
|
||||
if ( ! $this->should_handle( $event_type_info['level'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$template = $block->get_root_template();
|
||||
$container = $block->get_parent();
|
||||
|
||||
$this->add_template_event( $event_type_info, $template, $container, $block, $additional_info );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the logger handle a given level?
|
||||
*
|
||||
* @param int $level Level to check.
|
||||
*/
|
||||
private function should_handle( $level ) {
|
||||
return $this->threshold_severity <= \WC_Log_Levels::get_level_severity( $level );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a template event.
|
||||
*
|
||||
* @param array $event_type_info Event type info.
|
||||
* @param BlockTemplateInterface $template Template.
|
||||
* @param ContainerInterface $container Container.
|
||||
* @param BlockInterface $block Block.
|
||||
* @param array $additional_info Additional info.
|
||||
*/
|
||||
private function add_template_event( array $event_type_info, BlockTemplateInterface $template, ContainerInterface $container, BlockInterface $block, array $additional_info = array() ) {
|
||||
$template_id = $template->get_id();
|
||||
|
||||
if ( ! isset( $this->all_template_events[ $template_id ] ) ) {
|
||||
$this->all_template_events[ $template_id ] = array();
|
||||
$this->templates[ $template_id ] = $template;
|
||||
}
|
||||
|
||||
$template_events = &$this->all_template_events[ $template_id ];
|
||||
|
||||
$template_events[] = array(
|
||||
'level' => $event_type_info['level'],
|
||||
'event_type' => $event_type_info['event_type'],
|
||||
'message' => $event_type_info['message'],
|
||||
'container' => $container,
|
||||
'block' => $block,
|
||||
'additional_info' => $additional_info,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -87,7 +404,7 @@ class BlockTemplateLogger {
|
|||
* @param string $message Message to log.
|
||||
* @param array $info Additional info to log.
|
||||
*/
|
||||
private function format_message( string $message, array $info = [] ): string {
|
||||
private function format_message( string $message, array $info = array() ): string {
|
||||
$formatted_message = sprintf(
|
||||
"%s\n%s",
|
||||
$message,
|
||||
|
@ -137,12 +454,12 @@ class BlockTemplateLogger {
|
|||
* @param \Exception $exception Exception to format.
|
||||
*/
|
||||
private function format_exception( \Exception $exception ): array {
|
||||
return [
|
||||
return array(
|
||||
'message' => $exception->getMessage(),
|
||||
'source' => "{$exception->getFile()}: {$exception->getLine()}",
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
|
||||
'trace' => print_r( $this->format_exception_trace( $exception->getTrace() ), true ),
|
||||
];
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,7 +468,7 @@ class BlockTemplateLogger {
|
|||
* @param array $trace Exception trace to format.
|
||||
*/
|
||||
private function format_exception_trace( array $trace ): array {
|
||||
$formatted_trace = [];
|
||||
$formatted_trace = array();
|
||||
|
||||
foreach ( $trace as $source ) {
|
||||
$formatted_trace[] = "{$source['file']}: {$source['line']}";
|
||||
|
|
Loading…
Reference in New Issue