Yaffs site version 1.1
[yaffs-website] / vendor / consolidation / output-formatters / src / Transformations / Wrap / CalculateWidths.php
diff --git a/vendor/consolidation/output-formatters/src/Transformations/Wrap/CalculateWidths.php b/vendor/consolidation/output-formatters/src/Transformations/Wrap/CalculateWidths.php
new file mode 100644 (file)
index 0000000..04af092
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+namespace Consolidation\OutputFormatters\Transformations\Wrap;
+
+use Symfony\Component\Console\Helper\TableStyle;
+
+/**
+ * Calculate column widths for table cells.
+ *
+ * Influenced by Drush and webmozart/console.
+ */
+class CalculateWidths
+{
+    public function __construct()
+    {
+    }
+
+    /**
+     * Given the total amount of available space, and the width of
+     * the columns to place, calculate the optimum column widths to use.
+     */
+    public function calculate($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths)
+    {
+        // First, check to see if all columns will fit at their full widths.
+        // If so, do no further calculations. (This may be redundant with
+        // the short column width calculation.)
+        if ($dataWidths->totalWidth() <= $availableWidth) {
+            return $dataWidths->enforceMinimums($minimumWidths);
+        }
+
+        // Get the short columns first. If there are none, then distribute all
+        // of the available width among the remaining columns.
+        $shortColWidths = $this->getShortColumns($availableWidth, $dataWidths, $minimumWidths);
+        if ($shortColWidths->isEmpty()) {
+            return $this->distributeLongColumns($availableWidth, $dataWidths, $minimumWidths);
+        }
+
+        // If some short columns were removed, then account for the length
+        // of the removed columns and make a recursive call (since the average
+        // width may be higher now, if the removed columns were shorter in
+        // length than the previous average).
+        $availableWidth -= $shortColWidths->totalWidth();
+        $remainingWidths = $dataWidths->removeColumns($shortColWidths->keys());
+        $remainingColWidths = $this->calculate($availableWidth, $remainingWidths, $minimumWidths);
+
+        return $shortColWidths->combine($remainingColWidths);
+    }
+
+    /**
+     * Calculate the longest cell data from any row of each of the cells.
+     */
+    public function calculateLongestCell($rows)
+    {
+        return $this->calculateColumnWidths(
+            $rows,
+            function ($cell) {
+                return strlen($cell);
+            }
+        );
+    }
+
+    /**
+     * Calculate the longest word and longest line in the provided data.
+     */
+    public function calculateLongestWord($rows)
+    {
+        return $this->calculateColumnWidths(
+            $rows,
+            function ($cell) {
+                return static::longestWordLength($cell);
+            }
+        );
+    }
+
+    protected function calculateColumnWidths($rows, callable $fn)
+    {
+        $widths = [];
+
+        // Examine each row and find the longest line length and longest
+        // word in each column.
+        foreach ($rows as $rowkey => $row) {
+            foreach ($row as $colkey => $cell) {
+                $value = $fn($cell);
+                if ((!isset($widths[$colkey]) || ($widths[$colkey] < $value))) {
+                    $widths[$colkey] = $value;
+                }
+            }
+        }
+
+        return new ColumnWidths($widths);
+    }
+
+    /**
+     * Return all of the columns whose longest line length is less than or
+     * equal to the average width.
+     */
+    public function getShortColumns($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths)
+    {
+        $averageWidth = $dataWidths->averageWidth($availableWidth);
+        $shortColWidths = $dataWidths->findShortColumns($averageWidth);
+        return $shortColWidths->enforceMinimums($minimumWidths);
+    }
+
+    /**
+     * Distribute the remainig space among the columns that were not
+     * included in the list of "short" columns.
+     */
+    public function distributeLongColumns($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths)
+    {
+        // First distribute the remainder without regard to the minimum widths.
+        $result = $dataWidths->distribute($availableWidth);
+
+        // Find columns that are shorter than their minimum width.
+        $undersized = $result->findUndersizedColumns($minimumWidths);
+
+        // Nothing too small? Great, we're done!
+        if ($undersized->isEmpty()) {
+            return $result;
+        }
+
+        // Take out the columns that are too small and redistribute the rest.
+        $availableWidth -= $undersized->totalWidth();
+        $remaining = $dataWidths->removeColumns($undersized->keys());
+        $distributeRemaining = $this->distributeLongColumns($availableWidth, $remaining, $minimumWidths);
+
+        return $undersized->combine($distributeRemaining);
+    }
+
+    /**
+     * Return the length of the longest word in the string.
+     * @param string $str
+     * @return int
+     */
+    protected static function longestWordLength($str)
+    {
+        $words = preg_split('#[ /-]#', $str);
+        $lengths = array_map(function ($s) {
+            return strlen($s);
+        }, $words);
+        return max($lengths);
+    }
+}