X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;f=vendor%2Fconsolidation%2Foutput-formatters%2Fsrc%2FTransformations%2FWordWrapper.php;h=36f9b88d04110df649c62b99062043d979aae3d0;hb=e0411c4e83ba0d079034db83c3f7f55be24a0e35;hp=18519d077eaa5006f0331c71b396bbd13b055d16;hpb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;p=yaffs-website diff --git a/vendor/consolidation/output-formatters/src/Transformations/WordWrapper.php b/vendor/consolidation/output-formatters/src/Transformations/WordWrapper.php index 18519d077..36f9b88d0 100644 --- a/vendor/consolidation/output-formatters/src/Transformations/WordWrapper.php +++ b/vendor/consolidation/output-formatters/src/Transformations/WordWrapper.php @@ -1,12 +1,14 @@ width = $width; + $this->minimumWidths = new ColumnWidths(); } /** @@ -40,7 +43,15 @@ class WordWrapper */ public function setMinimumWidths($minimumWidths) { - $this->minimumWidths = $minimumWidths; + $this->minimumWidths = new ColumnWidths($minimumWidths); + } + + /** + * Set the minimum width of just one column + */ + public function minimumWidth($colkey, $width) + { + $this->minimumWidths->setWidth($colkey, $width); } /** @@ -50,19 +61,18 @@ class WordWrapper */ public function wrap($rows, $widths = []) { - // If the width was not set, then disable wordwrap. - if (!$this->width) { + $auto_widths = $this->calculateWidths($rows, $widths); + + // If no widths were provided, then disable wrapping + if ($auto_widths->isEmpty()) { return $rows; } - // Calculate the column widths to use based on the content. - $auto_widths = $this->columnAutowidth($rows, $widths); - // Do wordwrap on all cells. $newrows = array(); foreach ($rows as $rowkey => $row) { foreach ($row as $colkey => $cell) { - $newrows[$rowkey][$colkey] = $this->wrapCell($cell, $auto_widths[$colkey]); + $newrows[$rowkey][$colkey] = $this->wrapCell($cell, $auto_widths->width($colkey)); } } @@ -70,158 +80,43 @@ class WordWrapper } /** - * Wrap one cell. Guard against modifying non-strings and - * then call through to wordwrap(). - * - * @param mixed $cell - * @param string $cellWidth - * @return mixed - */ - protected function wrapCell($cell, $cellWidth) - { - if (!is_string($cell)) { - return $cell; - } - return wordwrap($cell, $cellWidth, "\n", true); - } - - /** - * Determine the best fit for column widths. Ported from Drush. - * - * @param array $rows The rows to use for calculations. - * @param array $widths Manually specified widths of each column - * (in characters) - these will be left as is. + * Determine what widths we'll use for wrapping. */ - protected function columnAutowidth($rows, $widths) + protected function calculateWidths($rows, $widths = []) { - $auto_widths = $widths; - - // First we determine the distribution of row lengths in each column. - // This is an array of descending character length keys (i.e. starting at - // the rightmost character column), with the value indicating the number - // of rows where that character column is present. - $col_dist = []; - // We will also calculate the longest word in each column - $max_word_lens = []; - foreach ($rows as $rowkey => $row) { - foreach ($row as $col_id => $cell) { - $longest_word_len = static::longestWordLength($cell); - if ((!isset($max_word_lens[$col_id]) || ($max_word_lens[$col_id] < $longest_word_len))) { - $max_word_lens[$col_id] = $longest_word_len; - } - if (empty($widths[$col_id])) { - $length = strlen($cell); - if ($length == 0) { - $col_dist[$col_id][0] = 0; - } - while ($length > 0) { - if (!isset($col_dist[$col_id][$length])) { - $col_dist[$col_id][$length] = 0; - } - $col_dist[$col_id][$length]++; - $length--; - } - } - } + // Widths must be provided in some form or another, or we won't wrap. + if (empty($widths) && !$this->width) { + return new ColumnWidths(); } - foreach ($col_dist as $col_id => $count) { - // Sort the distribution in decending key order. - krsort($col_dist[$col_id]); - // Initially we set all columns to their "ideal" longest width - // - i.e. the width of their longest column. - $auto_widths[$col_id] = max(array_keys($col_dist[$col_id])); - } - - // We determine what width we have available to use, and what width the - // above "ideal" columns take up. - $available_width = $this->width - ($this->extraPaddingAtBeginningOfLine + $this->extraPaddingAtEndOfLine + (count($auto_widths) * $this->paddingInEachCell)); - $auto_width_current = array_sum($auto_widths); - - // If we cannot fit into the minimum width anyway, then just return - // the max word length of each column as the 'ideal' - $minimumIdealLength = array_sum($this->minimumWidths); - if ($minimumIdealLength && ($available_width < $minimumIdealLength)) { - return $max_word_lens; - } + // Technically, `$widths`, if provided here, should be used + // as the exact widths to wrap to. For now we'll just treat + // these as minimum widths + $minimumWidths = $this->minimumWidths->combine(new ColumnWidths($widths)); - // If we need to reduce a column so that we can fit the space we use this - // loop to figure out which column will cause the "least wrapping", - // (relative to the other columns) and reduce the width of that column. - while ($auto_width_current > $available_width) { - list($column, $width) = $this->selectColumnToReduce($col_dist, $auto_widths, $max_word_lens); + $calculator = new CalculateWidths(); + $dataCellWidths = $calculator->calculateLongestCell($rows); - if (!$column || $width <= 1) { - // If we have reached a width of 1 then give up, so wordwrap can still progress. - break; - } - // Reduce the width of the selected column. - $auto_widths[$column]--; - // Reduce our overall table width counter. - $auto_width_current--; - // Remove the corresponding data from the disctribution, so next time - // around we use the data for the row to the left. - unset($col_dist[$column][$width]); - } - return $auto_widths; - } + $availableWidth = $this->width - $dataCellWidths->paddingSpace($this->paddingInEachCell, $this->extraPaddingAtEndOfLine, $this->extraPaddingAtBeginningOfLine); - protected function selectColumnToReduce($col_dist, $auto_widths, $max_word_lens) - { - $column = false; - $count = 0; - $width = 0; - foreach ($col_dist as $col_id => $counts) { - // Of the columns whose length is still > than the the lenght - // of their maximum word length - if ($auto_widths[$col_id] > $max_word_lens[$col_id]) { - if ($this->shouldSelectThisColumn($count, $counts, $width)) { - $column = $col_id; - $count = current($counts); - $width = key($counts); - } - } - } - if ($column !== false) { - return [$column, $width]; - } - foreach ($col_dist as $col_id => $counts) { - if (empty($this->minimumWidths) || ($auto_widths[$col_id] > $this->minimumWidths[$col_id])) { - if ($this->shouldSelectThisColumn($count, $counts, $width)) { - $column = $col_id; - $count = current($counts); - $width = key($counts); - } - } - } - return [$column, $width]; - } + $this->minimumWidths->adjustMinimumWidths($availableWidth, $dataCellWidths); - protected function shouldSelectThisColumn($count, $counts, $width) - { - return - // If we are just starting out, select the first column. - ($count == 0) || - // OR: if this column would cause less wrapping than the currently - // selected column, then select it. - (current($counts) < $count) || - // OR: if this column would cause the same amount of wrapping, but is - // longer, then we choose to wrap the longer column (proportionally - // less wrapping, and helps avoid triple line wraps). - (current($counts) == $count && key($counts) > $width); + return $calculator->calculate($availableWidth, $dataCellWidths, $minimumWidths); } /** - * Return the length of the longest word in the string. - * @param string $str - * @return int + * Wrap one cell. Guard against modifying non-strings and + * then call through to wordwrap(). + * + * @param mixed $cell + * @param string $cellWidth + * @return mixed */ - protected static function longestWordLength($str) + protected function wrapCell($cell, $cellWidth) { - $words = preg_split('/[ -]/', $str); - $lengths = array_map(function ($s) { - return strlen($s); - }, $words); - return max($lengths); + if (!is_string($cell)) { + return $cell; + } + return wordwrap($cell, $cellWidth, "\n", true); } }