Chris@0: ' . t('About') . ''; Chris@18: $output .= '

' . t('The Text module allows you to create short and long text fields with optional summaries. See the Field module help and the Field UI help pages for general information on fields and how to create and manage them. For more information, see the online documentation for the Text module.', [':field' => Url::fromRoute('help.page', ['name' => 'field'])->toString(), ':field_ui' => (\Drupal::moduleHandler()->moduleExists('field_ui')) ? Url::fromRoute('help.page', ['name' => 'field_ui'])->toString() : '#', ':text_documentation' => 'https://www.drupal.org/documentation/modules/text']) . '

'; Chris@0: $output .= '

' . t('Uses') . '

'; Chris@0: $output .= '
'; Chris@0: $output .= '
' . t('Managing and displaying text fields') . '
'; Chris@18: $output .= '
' . t('The settings and display of the text field can be configured separately. See the Field UI help for more information on how to manage fields and their display.', [':field_ui' => (\Drupal::moduleHandler()->moduleExists('field_ui')) ? Url::fromRoute('help.page', ['name' => 'field_ui'])->toString() : '#']) . '
'; Chris@0: $output .= '
' . t('Creating short text fields') . '
'; Chris@0: $output .= '
' . t('If you choose Text (plain) or Text (formatted) as the field type on the Manage fields page, then a field with a single row is displayed. You can change the maximum text length in the Field settings when you set up the field.') . '
'; Chris@0: $output .= '
' . t('Creating long text fields') . '
'; Chris@0: $output .= '
' . t('If you choose Text (plain, long), Text (formatted, long), or Text (formatted, long, with summary) on the Manage fields page, then users can insert text of unlimited length. On the Manage form display page, you can set the number of rows that are displayed to users.') . '
'; Chris@0: $output .= '
' . t('Trimming the text length') . '
'; Chris@0: $output .= '
' . t('On the Manage display page you can choose to display a trimmed version of the text, and if so, where to cut off the text.') . '
'; Chris@0: $output .= '
' . t('Displaying summaries instead of trimmed text') . '
'; Chris@0: $output .= '
' . t('As an alternative to using a trimmed version of the text, you can enter a separate summary by choosing the Text (formatted, long, with summary) field type on the Manage fields page. Even when Summary input is enabled, and summaries are provided, you can display trimmed text nonetheless by choosing the appropriate format on the Manage display page.') . '
'; Chris@0: $output .= '
' . t('Using text formats and editors') . '
'; Chris@18: $output .= '
' . t('If you choose Text (plain) or Text (plain, long) you restrict the input to Plain text only. If you choose Text (formatted), Text (formatted, long), or Text (formatted, long with summary) you allow users to write formatted text. Which options are available to individual users depends on the settings on the Text formats and editors page.', [':formats' => Url::fromRoute('filter.admin_overview')->toString()]) . '
'; Chris@0: $output .= '
'; Chris@0: return $output; Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Generates a trimmed, formatted version of a text field value. Chris@0: * Chris@0: * If the end of the summary is not indicated using the delimiter Chris@0: * then we generate the summary automatically, trying to end it at a sensible Chris@0: * place such as the end of a paragraph, a line break, or the end of a sentence Chris@0: * (in that order of preference). Chris@0: * Chris@0: * @param $text Chris@0: * The content for which a summary will be generated. Chris@0: * @param $format Chris@0: * The format of the content. If the line break filter is present then we Chris@0: * treat newlines embedded in $text as line breaks. If the htmlcorrector Chris@0: * filter is present, it will be run on the generated summary (if different Chris@0: * from the incoming $text). Chris@0: * @param $size Chris@0: * The desired character length of the summary. If omitted, the default value Chris@0: * will be used. Ignored if the special delimiter is present in $text. Chris@0: * Chris@0: * @return Chris@0: * The generated summary. Chris@0: */ Chris@0: function text_summary($text, $format = NULL, $size = NULL) { Chris@0: Chris@0: if (!isset($size)) { Chris@0: $size = \Drupal::config('text.settings')->get('default_summary_length'); Chris@0: } Chris@0: Chris@0: // Find where the delimiter is in the body Chris@0: $delimiter = strpos($text, ''); Chris@0: Chris@0: // If the size is zero, and there is no delimiter, the entire body is the summary. Chris@0: if ($size == 0 && $delimiter === FALSE) { Chris@0: return $text; Chris@0: } Chris@0: Chris@0: // If a valid delimiter has been specified, use it to chop off the summary. Chris@0: if ($delimiter !== FALSE) { Chris@0: return substr($text, 0, $delimiter); Chris@0: } Chris@0: Chris@0: // Retrieve the filters of the specified text format, if any. Chris@0: if (isset($format)) { Chris@14: $filter_format = FilterFormat::load($format); Chris@0: // If the specified format does not exist, return nothing. $text is already Chris@0: // filtered text, but the remainder of this function will not be able to Chris@0: // ensure a sane and secure summary. Chris@14: if (!$filter_format || !($filters = $filter_format->filters())) { Chris@0: return ''; Chris@0: } Chris@0: } Chris@0: Chris@0: // If we have a short body, the entire body is the summary. Chris@17: if (mb_strlen($text) <= $size) { Chris@0: return $text; Chris@0: } Chris@0: Chris@0: // If the delimiter has not been specified, try to split at paragraph or Chris@0: // sentence boundaries. Chris@0: Chris@0: // The summary may not be longer than maximum length specified. Initial slice. Chris@0: $summary = Unicode::truncate($text, $size); Chris@0: Chris@0: // Store the actual length of the UTF8 string -- which might not be the same Chris@0: // as $size. Chris@0: $max_rpos = strlen($summary); Chris@0: Chris@0: // How much to cut off the end of the summary so that it doesn't end in the Chris@0: // middle of a paragraph, sentence, or word. Chris@0: // Initialize it to maximum in order to find the minimum. Chris@0: $min_rpos = $max_rpos; Chris@0: Chris@0: // Store the reverse of the summary. We use strpos on the reversed needle and Chris@0: // haystack for speed and convenience. Chris@0: $reversed = strrev($summary); Chris@0: Chris@0: // Build an array of arrays of break points grouped by preference. Chris@0: $break_points = []; Chris@0: Chris@0: // A paragraph near the end of sliced summary is most preferable. Chris@0: $break_points[] = ['

' => 0]; Chris@0: Chris@0: // If no complete paragraph then treat line breaks as paragraphs. Chris@0: $line_breaks = ['
' => 6, '
' => 4]; Chris@0: // Newline only indicates a line break if line break converter Chris@0: // filter is present. Chris@0: if (isset($format) && $filters->has('filter_autop') && $filters->get('filter_autop')->status) { Chris@0: $line_breaks["\n"] = 1; Chris@0: } Chris@0: $break_points[] = $line_breaks; Chris@0: Chris@0: // If the first paragraph is too long, split at the end of a sentence. Chris@0: $break_points[] = ['. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1]; Chris@0: Chris@0: // Iterate over the groups of break points until a break point is found. Chris@0: foreach ($break_points as $points) { Chris@0: // Look for each break point, starting at the end of the summary. Chris@0: foreach ($points as $point => $offset) { Chris@0: // The summary is already reversed, but the break point isn't. Chris@0: $rpos = strpos($reversed, strrev($point)); Chris@0: if ($rpos !== FALSE) { Chris@0: $min_rpos = min($rpos + $offset, $min_rpos); Chris@0: } Chris@0: } Chris@0: Chris@0: // If a break point was found in this group, slice and stop searching. Chris@0: if ($min_rpos !== $max_rpos) { Chris@0: // Don't slice with length 0. Length must be <0 to slice from RHS. Chris@0: $summary = ($min_rpos === 0) ? $summary : substr($summary, 0, 0 - $min_rpos); Chris@0: break; Chris@0: } Chris@0: } Chris@0: Chris@0: // If the htmlcorrector filter is present, apply it to the generated summary. Chris@0: if (isset($format) && $filters->has('filter_htmlcorrector') && $filters->get('filter_htmlcorrector')->status) { Chris@0: $summary = Html::normalize($summary); Chris@0: } Chris@0: Chris@0: return $summary; Chris@0: }