| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | namespace Consolidation\OutputFormatters\Transformations\Wrap; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | use Symfony\Component\Console\Helper\TableStyle; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  * Calculate column widths for table cells. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  * Influenced by Drush and webmozart/console. | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 10 |  |  |  */ | 
            
                                                                        
                            
            
                                    
            
            
                | 11 |  |  | class CalculateWidths | 
            
                                                                        
                            
            
                                    
            
            
                | 12 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |     public function __construct() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |     { | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 15 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 16 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 17 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 18 |  |  |      * Given the total amount of available space, and the width of | 
            
                                                                        
                            
            
                                    
            
            
                | 19 |  |  |      * the columns to place, calculate the optimum column widths to use. | 
            
                                                                        
                            
            
                                    
            
            
                | 20 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |     public function calculate($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |         // First, check to see if all columns will fit at their full widths. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |         // If so, do no further calculations. (This may be redundant with | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |         // the short column width calculation.) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |         if ($dataWidths->totalWidth() <= $availableWidth) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |             return $dataWidths->enforceMinimums($minimumWidths); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |         // Get the short columns first. If there are none, then distribute all | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |         // of the available width among the remaining columns. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |         $shortColWidths = $this->getShortColumns($availableWidth, $dataWidths, $minimumWidths); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |         if ($shortColWidths->isEmpty()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |             return $this->distributeLongColumns($availableWidth, $dataWidths, $minimumWidths); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |         // If some short columns were removed, then account for the length | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |         // of the removed columns and make a recursive call (since the average | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |         // width may be higher now, if the removed columns were shorter in | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |         // length than the previous average). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |         $availableWidth -= $shortColWidths->totalWidth(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |         $remainingWidths = $dataWidths->removeColumns($shortColWidths->keys()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |         $remainingColWidths = $this->calculate($availableWidth, $remainingWidths, $minimumWidths); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |         return $shortColWidths->combine($remainingColWidths); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 46 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 47 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 48 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 49 |  |  |      * Calculate the longest cell data from any row of each of the cells. | 
            
                                                                        
                            
            
                                    
            
            
                | 50 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     public function calculateLongestCell($rows) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |         return $this->calculateColumnWidths( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |             $rows, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |             function ($cell) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |                 return strlen($cell); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |         ); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 59 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 60 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 61 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 62 |  |  |      * Calculate the longest word and longest line in the provided data. | 
            
                                                                        
                            
            
                                    
            
            
                | 63 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |     public function calculateLongestWord($rows) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |         return $this->calculateColumnWidths( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |             $rows, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |             function ($cell) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |                 return static::longestWordLength($cell); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |         ); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 72 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |     protected function calculateColumnWidths($rows, callable $fn) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |         $widths = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |         // Examine each row and find the longest line length and longest | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |         // word in each column. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |         foreach ($rows as $rowkey => $row) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |             foreach ($row as $colkey => $cell) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |                 $value = $fn($cell); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |                 if ((!isset($widths[$colkey]) || ($widths[$colkey] < $value))) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |                     $widths[$colkey] = $value; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |         return new ColumnWidths($widths); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 90 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 91 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 92 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 93 |  |  |      * Return all of the columns whose longest line length is less than or | 
            
                                                                        
                            
            
                                    
            
            
                | 94 |  |  |      * equal to the average width. | 
            
                                                                        
                            
            
                                    
            
            
                | 95 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |     public function getShortColumns($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |         $averageWidth = $dataWidths->averageWidth($availableWidth); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         $shortColWidths = $dataWidths->findShortColumns($averageWidth); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |         return $shortColWidths->enforceMinimums($minimumWidths); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 101 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 102 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 103 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 104 |  |  |      * Distribute the remainig space among the columns that were not | 
            
                                                                        
                            
            
                                    
            
            
                | 105 |  |  |      * included in the list of "short" columns. | 
            
                                                                        
                            
            
                                    
            
            
                | 106 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |     public function distributeLongColumns($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |         // First distribute the remainder without regard to the minimum widths. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         $result = $dataWidths->distribute($availableWidth); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |         // Find columns that are shorter than their minimum width. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |         $undersized = $result->findUndersizedColumns($minimumWidths); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |         // Nothing too small? Great, we're done! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |         if ($undersized->isEmpty()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |             return $result; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         // Take out the columns that are too small and redistribute the rest. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |         $availableWidth -= $undersized->totalWidth(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |         $remaining = $dataWidths->removeColumns($undersized->keys()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |         $distributeRemaining = $this->distributeLongColumns($availableWidth, $remaining, $minimumWidths); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |         return $undersized->combine($distributeRemaining); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 126 |  |  |     } | 
            
                                                                        
                            
            
                                    
            
            
                | 127 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 128 |  |  |     /** | 
            
                                                                        
                            
            
                                    
            
            
                | 129 |  |  |      * Return the length of the longest word in the string. | 
            
                                                                        
                            
            
                                    
            
            
                | 130 |  |  |      * @param string $str | 
            
                                                                        
                            
            
                                    
            
            
                | 131 |  |  |      * @return int | 
            
                                                                        
                            
            
                                    
            
            
                | 132 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |     protected static function longestWordLength($str) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |         $words = preg_split('#[ /-]#', $str); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |         $lengths = array_map(function ($s) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |             return strlen($s); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |         }, $words); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |         return max($lengths); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 140 |  |  |     } | 
            
                                                        
            
                                    
            
            
                | 141 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 142 |  |  |  |