); $trimmed = mb_substr( $pure_text, 0, $max_length ); if ( 'characters_including_spaces' === $count_type ) { return $trimmed; } preg_match_all( '/([\s]+)/', $trimmed, $spaces ); $space_count = ! empty( $spaces[0] ) ? count( $spaces[0] ) : 0; return mb_substr( $pure_text, 0, $max_length + $space_count ); } /** * Generates the summary text from a string of text. It's not ideal * but allows keeping the editor and frontend consistent. * * NOTE: If editing, keep it in sync with generateSummary function from * plugins/woocommerce/client/blocks/assets/js/base/components/summary/utils.ts! * * Once HTML API allow for HTML manipulation both functions (PHP and JS) * should be updated to solution fully respecting the word count. * https://github.com/woocommerce/woocommerce/issues/52835 * * @param string $source Source text. * @param int $max_length Limit number of items returned if text has multiple paragraphs. * @return string Generated summary. */ private function generate_summary( $source, $max_length ) { $count_type = wp_get_word_count_type(); $source_with_paragraphs = wpautop( $source ); $source_word_count = $this->count_text( $source_with_paragraphs, $count_type ); if ( $source_word_count <= $max_length ) { return $source_with_paragraphs; } $first_paragraph = $this->get_first_paragraph( $source_with_paragraphs ); $first_paragraph_word_count = $this->count_text( $first_paragraph, $count_type ); if ( $first_paragraph_word_count <= $max_length ) { return $first_paragraph; } if ( 'words' === $count_type ) { return wpautop( wp_trim_words( $first_paragraph, $max_length ) ); } return $this->trim_characters( $first_paragraph, $max_length, $count_type ) . '…'; } /** * Include and render the block. * * @param array $attributes Block attributes. Default empty array. * @param string $content Block content. Default empty string. * @param WP_Block $block Block instance. * @return string Rendered block type output. */ protected function render( $attributes, $content, $block ) { if ( ! empty( $content ) ) { parent::register_block_type_assets(); $this->register_chunk_translations( [ $this->block_name ] ); return $content; } $post_id = $block->context['postId'] ?? ''; $product = wc_get_product( $post_id ); if ( ! $product ) { return ''; } $show_description_if_empty = isset( $attributes['showDescriptionIfEmpty'] ) && $attributes['showDescriptionIfEmpty']; $source = $this->get_source( $product, $show_description_if_empty ); if ( ! $source ) { return ''; } $summary_length = isset( $attributes['summaryLength'] ) ? $attributes['summaryLength'] : false; $link_text = isset( $attributes['linkText'] ) ? $attributes['linkText'] : ''; $show_link = isset( $attributes['showLink'] ) && $attributes['showLink']; $summary = $summary_length ? $this->generate_summary( $source, $summary_length ) : wpautop( $source ); $final_summary = $show_link && $link_text ? $summary . $this->create_anchor( $product, $link_text ) : $summary; $styles_and_classes = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes ); return sprintf( '
%3$s
', esc_attr( $styles_and_classes['classes'] ), esc_attr( $styles_and_classes['styles'] ?? '' ), $final_summary ); } }