File: //home/globfdxw/www/wp-content/plugins/wpforms-pdf/src/Notifications/Fields/Richtext.php
<?php
namespace WPFormsPDF\Notifications\Fields;
use DOMXPath;
/**
* Class Richtext field.
*
* @since 1.2.0
*/
class Richtext {
/**
* Class constructor.
*
* @since 1.2.0
*
* @return void
*/
public function __construct() {
$this->hooks();
}
/**
* Register hooks.
*
* @since 1.2.0
*
* @return void
*/
private function hooks(): void {
add_filter(
'wpforms_pdf_notifications_fields_field_message_html_richtext',
[ $this, 'field_row_html_value' ],
100,
7
);
}
/**
* Transform richtext field message HTML to multiple rows by paragraphs.
*
* @since 1.2.0
*
* @param string|mixed $field_markup Field HTML row markup.
* @param array $field Field data.
* @param array $form_data Form data.
* @param array $template Template data.
*
* @return string
* @noinspection PhpUnusedParameterInspection
*/
public function field_row_html_value( $field_markup, array $field, array $form_data, array $template ): string { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$field_markup = (string) $field_markup;
if ( $field_markup === '' ) {
return $field_markup;
}
list( $dom, $xpath ) = Helpers::load_dom( $field_markup );
$rows = $this->query_richtext_rows( $xpath );
if ( ! $rows || $rows->length === 0 ) {
return $field_markup;
}
for ( $i = $rows->length - 1; $i >= 0; $i-- ) {
$tr = $rows->item( $i );
$value_td = Helpers::get_value_cell( $xpath, $tr );
if ( ! $value_td ) {
continue;
}
$has_field_name = Helpers::has_name_cell( $xpath, $tr );
$value_html = Helpers::get_inner_html( $dom, $value_td );
$parts = $this->split_value_into_parts( $value_html );
$field_name_td_html = $has_field_name ? Helpers::get_name_cell_html( $dom, $xpath, $tr ) : '';
Helpers::replace_row_with_parts( $dom, $tr, 'field-richtext', $has_field_name, $field_name_td_html, $parts );
}
return Helpers::save_html( $dom );
}
/**
* Query richtext rows.
*
* @since 1.2.0
*
* @param DOMXPath $xpath XPath instance.
*
* @return DOMNodeList|false
*/
private function query_richtext_rows( DOMXPath $xpath ) {
return $xpath->query( '//tr[contains(@class,"field-richtext")]' );
}
/**
* Normalize and split into paragraph parts.
*
* @since 1.2.0
*
* @param string $value_html HTML of the value cell.
*
* @return array
*/
private function split_value_into_parts( string $value_html ): array {
// Normalize BR tags to be XML-friendly for DOMDocumentFragment::appendXML.
$value_html = preg_replace( '#<br\s*/?>#i', '<br />', $value_html );
// Strip outer <div> wrappers if present.
if ( preg_match( '#^<div[^>]*>(.*)</div>$#is', $value_html, $m ) ) {
$value_html = $m[1];
}
$parts = preg_split( '#</p>\s*<p>#i', $value_html );
// Ensure each part is wrapped in a single <p>...</p>.
foreach ( $parts as &$part ) {
$part = $this->ensure_paragraph_wrapped( $part );
// Double-sanitize BRs inside each part, in case wrapping introduced/moved text.
$part = preg_replace( '#<br\s*/?>#i', '<br />', $part );
}
unset( $part );
return $parts;
}
/**
* Ensures the provided string is wrapped within paragraph tags.
*
* @since 1.2.0
*
* @param string $part The string to be checked and wrapped with paragraph tags, if necessary.
*
* @return string
*/
private function ensure_paragraph_wrapped( string $part ): string {
$part = trim( $part );
if ( strpos( $part, '<p' ) !== 0 ) {
$part = '<p>' . $part;
}
if ( substr( $part, -4 ) !== '</p>' ) {
$part .= '</p>';
}
return $part;
}
}