AlkantarClanX12
| Current Path : /www/capitalgmcbuickregina_830/public/wp-content/plugins/wp-cerber/includes/ |
| Current File : /www/capitalgmcbuickregina_830/public/wp-content/plugins/wp-cerber/includes/cerber-ui-blocks.php |
<?php
/*
* Helpers, factory functions, and domain-specific functions.
*
* They encapsulate the logic for building complex, domain-specific CRB_UI_Element trees,
* providing a clean and simple API for the rest of the application.
*
*/
/**
* Creates an HTML link with a confirmation dialog.
*
* When the user clicks the link, a confirmation dialog is displayed with the specified message.
* If the user does not confirm, the action is cancelled, and the browser does not follow the lin
*
* @param string $url URL of the link.
* @param string $text Link text.
* @param string $msg Optional confirmation message.
* @param string $class Optional class for the <a> element.
*
* @return string The rendered HTML of the confirmation link.
*
* @see crb_confirmation_link()
*
* @since 9.6.9.6
*/
function crb_ui_confirmation_link( string $url, string $text, string $msg = '', string $class = '' ): string {
$props = [
'href' => $url,
'label' => $text,
'message' => $msg,
];
$attributes = [
'class' => $class,
];
$element = new CRB_UI_Element('confirmation_link', $props, $attributes);
return crb_ui_renderer()->render_element($element);
}
/**
* Wraps caller-supplied paragraphs in a bordered, margined message box.
*
* The paragraphs are enclosed in a single 'cerber-margin crb-rectangle-box'
* container. Each entry is either a ready-made CRB_UI_Element, typically a p
* node built with crb_ui_element() or crb_ui_link() when inline markup or
* attributes are needed, or a plain string or number. Scalar entries become
* escaped p elements, so pass unescaped text as is. Empty strings and
* unsupported entry types are dropped, mirroring the child normalization
* of crb_ui_element().
*
* @param array<int, CRB_UI_Element|string|int|float> $paragraphs Paragraphs in output order.
*
* @return CRB_UI_Element The message box element, an empty container when no paragraphs remain.
*
* @since 9.6.9.7
*/
function crb_ui_message_box( array $paragraphs ): CRB_UI_Element {
// Normalize scalar entries into escaped paragraph elements, keep prebuilt elements as is.
$paragraph_elements = [];
foreach ( $paragraphs as $paragraph_source ) {
if ( $paragraph_source instanceof CRB_UI_Element ) {
$paragraph_elements[] = $paragraph_source;
}
elseif ( is_string( $paragraph_source ) || is_numeric( $paragraph_source ) ) {
if ( (string) $paragraph_source !== '' ) {
$paragraph_elements[] = crb_ui_element( 'p', [], (string) $paragraph_source );
}
}
}
return new CRB_UI_Element( 'div', [], [ 'class' => 'cerber-margin crb-rectangle-box' ], $paragraph_elements );
}
/**
* Builds a message box describing a failed log data fetch.
*
* Produces the shared error notice for admin screens that load log entries
* through a Revalt-returning fetch. The first paragraph is a generic error
* message. Administrators with the manage_options capability additionally
* see the root cause message and its error code as separate paragraphs;
* other users see the top-level error message instead.
*
* @param Revalt $fetch_result A failed fetch result, has_errors() is expected to be true.
*
* @return CRB_UI_Element The message box element, ready for rendering.
*
* @since 9.8.4.1
*/
function crb_ui_log_fetch_error_box( Revalt $fetch_result ): CRB_UI_Element {
$notice_paragraphs = [ __( 'An error occurred while fetching log data.', 'wp-cerber' ) ];
// Internal diagnostics are shown to administrators only.
if ( current_user_can( 'manage_options' ) ) {
$root_cause = $fetch_result->get_root_cause();
if ( $root_cause ) {
$notice_paragraphs[] = $root_cause['message'];
$notice_paragraphs[] = 'ERROR CODE: ' . $root_cause['code'];
}
}
else {
$notice_paragraphs[] = $fetch_result->get_error_message();
}
return crb_ui_message_box( $notice_paragraphs );
}
/**
* Builds a structured CRB_UI_Element object representing a diagnostic section.
*
* @param string $title The main title of the section.
* @param mixed $content The main content, can be a string or a CRB_UI_Element.
* @param array $args Optional arguments: 'subtitle', 'copy_class'.
*
* @return CRB_UI_Element A fully constructed UI element for the diagnostic section.
*
* @since 9.6.9.5
*/
function crb_ui_make_diag_section( string $title, $content, array $args = [] ): CRB_UI_Element {
if ( is_string( $content ) ) {
$content_element = new CRB_UI_Element( 'text', [ 'content' => $content ] );
}
elseif ( $content instanceof CRB_UI_Element ) {
$content_element = $content;
}
else {
$content_element = new CRB_UI_Element( 'text', [ 'content' => 'Invalid Data Provided' ] );
}
$header_items = [ new CRB_UI_Element( 'h3', [ 'content' => $title ] ) ];
if ( $copy_class = $args['copy_class'] ?? '' ) {
$header_items[] = crb_ui_copy_to_clipboard( $copy_class );
}
$section_children = [ crb_ui_generate_html_flex( $header_items ) ];
if ( $subtitle = $args['subtitle'] ?? '' ) {
$section_children[] = new CRB_UI_Element( 'div', [ 'content' => $subtitle ], [ 'class' => 'crb-diag-subtitle' ] );
}
$section_children[] = new CRB_UI_Element( 'div', [], [ 'class' => 'crb-diag-inner' ], [ $content_element ] );
return new CRB_UI_Element(
'div',
[],
[ 'class' => 'crb-diag-section' ],
$section_children
);
}
/**
* Generates a plain HTML table using the UI Factory system.
*
* This function acts as a facade, preparing data and attributes before passing them
* to the 'standard_table' element renderer, which handles the complex logic.
*
* @param array $table_rows Table body rows.
* @param array $table_header Optional array of header labels.
* @param bool $first_header If true, adds 'crb-plain-fh' class.
* @param bool $eq If false, adds 'crb-plain-fcw' class.
*
* @return CRB_UI_Element The rendered HTML code for the table.
*
* @since 9.6.9.5
*
* This is a new generation of @see cerber_make_plain_table
*/
function crb_ui_make_plain_table( array $table_rows, array $table_header = [], bool $first_header = false, bool $eq = false ): CRB_UI_Element {
$table_classes = [ 'crb-monospace' ];
if ( $first_header ) {
$table_classes[] = 'crb-plain-fh';
}
if ( ! $eq ) {
$table_classes[] = 'crb-plain-fcw';
}
$props = [
'headers' => $table_header,
'data' => $table_rows,
];
$attributes = [
'class' => implode( ' ', $table_classes ),
];
$table_element = new CRB_UI_Element( 'standard_table', $props, $attributes );
return new CRB_UI_Element( 'div', [], [ 'class' => 'crb-plain-table' ], [ $table_element ] );
}
/**
* Helper function for creating a styled status span
*
* @param bool $is_positive
* @param string $text_yes
* @param string $text_no
*
* @return CRB_UI_Element
*
* @since 9.6.9.5
*/
function crb_ui_status_span( bool $is_positive, string $text_yes = 'YES', string $text_no = 'NO' ): CRB_UI_Element {
$text = $is_positive ? $text_yes : $text_no;
$color = $is_positive ? 'green' : 'red';
return new CRB_UI_Element(
'span',
[ 'content' => $text ],
[ 'style' => 'color: ' . $color ]
);
}
/**
* Helper function for creating a 'Copy To Clipboard' element
*
* @param string $source_class The class of the HTML elements to copy text content from.
* @param bool $plain If true, the plain inner text will be copied without tags and processing, otherwise <br/> tags will be converted into new lines and other tags will be removed.
*
* @return CRB_UI_Element
*
* @since 9.6.9.5
*
* This is a new generation of @see crb_copy_to_clipboard
*/
function crb_ui_copy_to_clipboard( string $source_class, $plain = true ): CRB_UI_Element {
return new CRB_UI_Element(
'link',
[
'label' => __( 'Copy To Clipboard', 'wp-cerber' ),
'href' => '#'
],
[
'class' => 'crb-copy-to-clipboard',
'data-plain_text' => ( $plain ? 1 : 0 ),
'data-copy_clipboard_class' => crb_boring_escape( $source_class )
]
);
}
/**
* Generates a flexible box layout using the UI Factory system.
*
* This function is a modern, drop-in replacement for the legacy version.
* It builds a structured element tree, ensuring safety, consistency, and maintainability.
*
* @param array $elements An array of child elements. Each item can be a string or a pre-existing CRB_UI_Element object for composition.
* @param string $class Optional CSS class for the flex container.
* @param string $justify The value for the 'justify-content' CSS property.
*
* @return CRB_UI_Element
*
* --- EXAMPLE OF USAGE ---
*
* Advanced usage with nested UI Elements
*
* $footer_items = [
* new CRB_UI_Element('span', ['content' => '© 2025 My App']),
* new CRB_UI_Element('link', ['label' => 'Terms of Service', 'href' => '/terms']),
* ];
*
* crb_ui_generate_html_flex($footer_items, 'site-footer', 'center');
*
* @since 9.6.9.5
*
* This is a new generation of @see crb_generate_html_flex
*/
function crb_ui_generate_html_flex( array $elements, string $class = '', string $justify = 'space-between' ): CRB_UI_Element {
$flex_container_atts = [
'class' => $class,
'style' => 'display: flex; justify-content: ' . crb_attr_escape( $justify ) . ';', // Sanitize justify value
];
// Wrap each entry in its own flex cell. Passing the entry as a single-item
// content list keeps the one-entry-one-cell mapping: crb_ui_element() keeps
// a pre-built element as is, turns a scalar into an escaped text node, and
// drops any non-conforming entry instead of expanding it into children.
$child_elements = [];
foreach ( $elements as $element_content ) {
$child_elements[] = crb_ui_element( 'div', [], [ $element_content ] );
}
return new CRB_UI_Element(
'div',
[],
$flex_container_atts,
$child_elements
);
}
/**
* Constructs a table-style hierarchical view of a key-value array using CRB_UI_Element.
*
* This function renders arrays as structured tables. It intelligently handles two formats:
*
* 1. Standard associative arrays (`['key' => 'value', ...]`).
* 2. Numerically indexed lists of pairs (`[['key1', 'value1'], ['key2', 'value2'], ...]`), which allows for duplicate keys (e.g., for displaying HTTP headers).
*
* If a value is itself an array, it will be recursively rendered as a nested table.
*
* Special object values with `element_class` and `element_value` properties are interpreted as decorated cells, allowing for per-cell styling.
*
* @param string $title Optional title for the table. Rendered in a dedicated top row, spanning both columns.
* @param array $fields Array of data to render. Nested arrays will be rendered recursively.
* @param bool $nested Internal flag used for recursive rendering of nested tables.
*
* @return CRB_UI_Element|null A renderable table element, or null if fields are empty. To generate HTML output, pass the result to the rendering engine.
*
* @example
*
* // --- EXAMPLE OF USAGE ---
*
* // Prepare your data
* $my_data = [
* 'System' => 'Linux',
* 'PHP Version' => phpversion(),
* 'Server Info' => [
* 'CPU' => 'Intel',
* 'RAM' => '16GB'
* ]
* ];
*
* // Call a factory function to get the element object
* $table_element = crb_ui_table_view('System Details', $my_data);
*
* // Render the element using the central renderer
* if ($table_element) {
* echo crb_ui_renderer()->render_element($table_element);
* }
*
* @since 9.6.9.7
*/
function crb_ui_table_view( string $title, array $fields, bool $nested = false ): ?CRB_UI_Element {
if ( empty( $fields ) ) {
return null;
}
// 1. Prepare attributes for the root <table> tag
$table_classes = [ 'crb-fields-table' ];
if ( $nested ) {
$table_classes[] = 'crb-sub-table';
}
else {
$table_classes[] = 'crb-top-table';
}
$table_attributes = [ 'class' => implode( ' ', $table_classes ) ];
// 2. Prepare the standard specification for the 'rich_table' renderer
$spec_props = [
'columns' => [
'key' => [ 'label' => '' ], // This table has no visible headers
'value' => [ 'label' => '' ],
],
'rows' => [],
'render_header' => false, // Headers are never rendered in this component
];
// 3. Handle the optional title by adding it as the first row
if ( $title ) {
$spec_props['rows'][] = [
'cells' => [
'key' => [
'content' => $title,
'attributes' => [ 'colspan' => 2 ]
],
]
];
}
// 4. Iterate through the fields, detect their format and transform them into standard row/cell specs
foreach ( $fields as $key => $value ) {
$row_key = null;
$row_value = null;
// Check the format of the input data array
if ( is_int( $key ) && is_array( $value )
&& count( $value ) === 2 && array_key_exists( 0, $value )
&& array_key_exists( 1, $value ) ) {
// This is a list format: [ ['key', 'value'], ... ] which has integer keys.
$row_key = $value[0];
$row_value = $value[1];
}
else {
// This is a standard associative array: [ 'key' => 'value', ... ]
$row_key = $key;
$row_value = $value;
}
$key_cell_attributes = [];
// Handle the special object format for cell attributes
if ( is_object( $row_value )
&& isset( $row_value->element_class )
&& isset( $row_value->element_value ) ) {
$key_cell_attributes['class'] = $row_value->element_class;
$row_value = $row_value->element_value;
}
$value_cell_content = null;
if ( is_array( $row_value ) ) {
// Recursively render nested arrays as nested tables
$value_cell_content = crb_ui_table_view( '', $row_value, true );
}
else {
$value_cell_content = new CRB_UI_Element( 'div', [ 'content' => (string) $row_value ] );
}
$spec_props['rows'][] = [
'cells' => [
'key' => [ 'content' => $row_key, 'attributes' => $key_cell_attributes ],
'value' => [ 'content' => $value_cell_content ],
]
];
}
return new CRB_UI_Element( 'rich_table', $spec_props, $table_attributes );
}