Completed
Pull Request — master (#43)
by Greg
02:07
created

WordWrapper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace Consolidation\OutputFormatters\Transformations;
3
4
class WordWrapper
5
{
6
    protected $width;
7
8
    public function __construct($width)
9
    {
10
        $this->width = $width;
11
    }
12
13
    /**
14
     * Wrap the cells in each part of the provided data table
15
     * @param array $data
0 ignored issues
show
Bug introduced by
There is no parameter named $data. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
16
     * @return array
17
     */
18
    public function wrap($rows, $widths = [])
19
    {
20
        // If the width was not set, then disable wordwrap.
21
        if (!$this->width) {
22
            return $rows;
23
        }
24
25
        // Calculate the column widths to use based on the content.
26
        $auto_widths = $this->columnAutowidth($rows, $widths);
27
28
        // Do wordwrap on all cells.
29
        $newrows = array();
30
        foreach ($rows as $rowkey => $row) {
31
            foreach ($row as $colkey => $cell) {
32
                $newrows[$rowkey][$colkey] = $this->wrapCell($cell, $auto_widths[$colkey]);
33
            }
34
        }
35
36
        return $newrows;
37
    }
38
39
    /**
40
     * Wrap one cell.  Guard against modifying non-strings and
41
     * then call through to wordwrap().
42
     *
43
     * @param mixed $cell
44
     * @param string $cellWidth
45
     * @return mixed
46
     */
47
    protected function wrapCell($cell, $cellWidth)
48
    {
49
        if (!is_string($cell)) {
50
            return $cell;
51
        }
52
        return wordwrap($cell, $cellWidth, "\n", true);
53
    }
54
55
    /**
56
     * Determine the best fit for column widths. Ported from Drush.
57
     *
58
     * @param array $rows The rows to use for calculations.
59
     * @param array $widths Manually specified widths of each column
60
     *   (in characters) - these will be left as is.
61
     */
62
    protected function columnAutowidth($rows, $widths)
63
    {
64
        $auto_widths = $widths;
65
66
        // First we determine the distribution of row lengths in each column.
67
        // This is an array of descending character length keys (i.e. starting at
68
        // the rightmost character column), with the value indicating the number
69
        // of rows where that character column is present.
70
        $col_dist = array();
71
        foreach ($rows as $rowkey => $row) {
72
            foreach ($row as $col_id => $cell) {
73
                if (empty($widths[$col_id])) {
74
                    $length = strlen($cell);
75
                    if ($length == 0) {
76
                        $col_dist[$col_id][0] = 0;
77
                    }
78
                    while ($length > 0) {
79
                        if (!isset($col_dist[$col_id][$length])) {
80
                            $col_dist[$col_id][$length] = 0;
81
                        }
82
                        $col_dist[$col_id][$length]++;
83
                        $length--;
84
                    }
85
                }
86
            }
87
        }
88
        foreach ($col_dist as $col_id => $count) {
89
            // Sort the distribution in decending key order.
90
            krsort($col_dist[$col_id]);
91
            // Initially we set all columns to their "ideal" longest width
92
            // - i.e. the width of their longest column.
93
            $auto_widths[$col_id] = max(array_keys($col_dist[$col_id]));
94
        }
95
96
        // We determine what width we have available to use, and what width the
97
        // above "ideal" columns take up.
98
        $available_width = $this->width - (count($auto_widths) * 2);
99
        $auto_width_current = array_sum($auto_widths);
100
101
        // If we need to reduce a column so that we can fit the space we use this
102
        // loop to figure out which column will cause the "least wrapping",
103
        // (relative to the other columns) and reduce the width of that column.
104
        while ($auto_width_current > $available_width) {
105
            $count = 0;
106
            $width = 0;
107
            foreach ($col_dist as $col_id => $counts) {
108
                // If we are just starting out, select the first column.
109
                if ($count == 0 ||
110
                 // OR: if this column would cause less wrapping than the currently
111
                 // selected column, then select it.
112
                 (current($counts) < $count) ||
113
                 // OR: if this column would cause the same amount of wrapping, but is
114
                 // longer, then we choose to wrap the longer column (proportionally
115
                 // less wrapping, and helps avoid triple line wraps).
116
                 (current($counts) == $count && key($counts) > $width)) {
117
                    // Select the column number, and record the count and current width
118
                    // for later comparisons.
119
                    $column = $col_id;
120
                    $count = current($counts);
121
                    $width = key($counts);
122
                }
123
            }
124
            if ($width <= 1) {
125
                // If we have reached a width of 1 then give up, so wordwrap can still progress.
126
                break;
127
            }
128
            // Reduce the width of the selected column.
129
            $auto_widths[$column]--;
0 ignored issues
show
Bug introduced by
The variable $column does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
130
            // Reduce our overall table width counter.
131
            $auto_width_current--;
132
            // Remove the corresponding data from the disctribution, so next time
133
            // around we use the data for the row to the left.
134
            unset($col_dist[$column][$width]);
135
        }
136
        return $auto_widths;
137
    }
138
}
139