Completed
Push — master ( 7aa5b3...a50dd6 )
by Basil
03:42 queued 01:27
created

ExportHelper::generateContentArray()   D

Complexity

Conditions 18
Paths 63

Size

Total Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 60
rs 4.8666
c 0
b 0
f 0
cc 18
nc 63
nop 4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace luya\helpers;
4
5
use luya\Exception;
6
use yii\base\Model;
7
use yii\db\QueryInterface;
8
9
/**
10
 * Exporting into Formats.
11
 *
12
 * @author Basil Suter <[email protected]>
13
 * @since 1.0.0
14
 */
15
class ExportHelper
16
{
17
    /**
18
     * Export an Array or QueryInterface instance into a CSV formated string.
19
     *
20
     * @param array|QueryInterface $input The data to export into a csv
21
     * @param array $keys Defines which keys should be packed into the generated CSV. The defined keys does not change the sort behavior of the generated csv.
22
     * @param string $header Whether the column name should be set as header inside the csv or not.
23
     * @param array $options Options {@since 1.8.0}
24
     * + `sort`: boolean, whether they row should be sorted by its keys, default is true.
25
     * @return string The generated CSV as string.
26
     */
27
    public static function csv($input, array $keys = [], $header = true, array $options = [])
28
    {
29
        $delimiter = ",";
30
        $input = self::transformInput($input);
31
        $array = self::generateContentArray($input, $keys, $header, $options);
0 ignored issues
show
Bug introduced by
It seems like $header defined by parameter $header on line 27 can also be of type string; however, luya\helpers\ExportHelper::generateContentArray() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
32
33
        return self::generateOutputString($array, $delimiter);
34
    }
35
36
    /**
37
     * Export an Array or QueryInterface instance into a Excel formatted string.
38
     *
39
     * @param array|QueryInterface $input
40
     * @param array $keys Defines which keys should be packed into the generated xlsx. The defined keys does not change the sort behavior of the generated xls.
41
     * @param bool $header
42
     * @param array $options Options {@since 1.8.0}
43
     * + `sort`: boolean, whether they row should be sorted by its keys, default is true.
44
     * @return mixed
45
     * @throws Exception
46
     * @since 1.0.4
47
     */
48
    public static function xlsx($input, array $keys = [], $header = true, array $options = [])
49
    {
50
        $input = self::transformInput($input);
51
52
        $array = self::generateContentArray($input, $keys, $header, $options);
53
54
        $writer = new XLSXWriter();
55
        $writer->writeSheet($array);
56
57
        return $writer->writeToString();
58
    }
59
60
    /**
61
     * Check type of input and return correct array.
62
     *
63
     * @param array|QueryInterface $input
64
     * @return array
65
     * @since 1.0.4
66
     */
67
    protected static function transformInput($input)
68
    {
69
        if ($input instanceof QueryInterface) {
70
            return $input->all();
71
        }
72
73
        return $input;
74
    }
75
76
    /**
77
     * Generate content by rows.
78
     *
79
     * @param array $contentRows
80
     * @param string $delimiter
0 ignored issues
show
Bug introduced by
There is no parameter named $delimiter. 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...
81
     * @param array $keys
82
     * @param bool $generateHeader
83
     * @param array $options Options {@since 1.8.0}
84
     * + `sort`: boolean, whether they row should be sorted by its keys, default is true.
85
     * @return array
86
     * @throws Exception
87
     * @since 1.0.4
88
     */
89
    protected static function generateContentArray($contentRows, array $keys, $generateHeader = true, $options  = [])
90
    {
91
        if (is_scalar($contentRows)) {
92
            throw new Exception("Content must be either an array, object or traversable.");
93
        }
94
95
        $attributeKeys = $keys;
96
        $header = [];
97
        $rows = [];
98
        $i = 0;
99
        foreach ($contentRows as $content) {
100
            // handle rows content
101
            if (!empty($keys) && is_array($content)) {
102
                foreach ($content as $k => $v) {
103
                    if (!in_array($k, $keys)) {
104
                        unset($content[$k]);
105
                    }
106
                }
107
            } elseif (!empty($keys) && is_object($content)) {
108
                $attributeKeys[get_class($content)] = $keys;
109
            }
110
            $row = ArrayHelper::toArray($content, $attributeKeys, false);
111
112
            if (ArrayHelper::getValue($options, 'sort', true)) {
113
                ksort($row);
114
            }
115
            
116
            $rows[$i] = $row;
117
118
            // handle header
119
            if ($i == 0 && $generateHeader) {
120
                if ($content instanceof Model) {
121
                    /** @var Model $content */
122
                    foreach ($content as $k => $v) {
123
                        if (empty($keys)) {
124
                            $header[$k] = $content->getAttributeLabel($k);
125
                        } elseif (in_array($k, $keys)) {
126
                            $header[$k] = $content->getAttributeLabel($k);
127
                        }
128
                    }
129
                } else {
130
                    $header = array_keys($rows[0]);
131
                }
132
133
                if (ArrayHelper::getValue($options, 'sort', true)) {
134
                    ksort($header);
135
                }
136
            }
137
138
            unset($row);
139
            gc_collect_cycles();
140
            $i++;
141
        }
142
143
        if ($generateHeader) {
144
            return ArrayHelper::merge([$header], $rows);
145
        }
146
147
        return $rows;
148
    }
149
150
    /**
151
     * Generate the output string with delimiters.
152
     *
153
     * @param array $input
154
     * @param string $delimiter
155
     * @return null|string
156
     * @since 1.0.4
157
     */
158
    protected static function generateOutputString(array $input, $delimiter)
159
    {
160
        $output = null;
161
        foreach ($input as $row) {
162
            $output.= self::generateRow($row, $delimiter, '"');
163
        }
164
165
        return $output;
166
    }
167
168
    /**
169
     * Generate a row by its items.
170
     *
171
     * @param array $row
172
     * @param string $delimiter
173
     * @param string $enclose
174
     * @return string
175
     * @since 1.0.4
176
     */
177
    protected static function generateRow(array $row, $delimiter, $enclose)
178
    {
179
        array_walk($row, function (&$item) use ($enclose) {
180
            if (is_bool($item)) {
181
                $item = (int) $item;
182
            } elseif (is_null($item)) {
183
                $item = '';
184
            } elseif (!is_scalar($item)) {
185
                $item = "[array]";
186
            }
187
            $item = $enclose.str_replace([
188
                '"',
189
            ], [
190
                '""',
191
            ], $item).$enclose;
192
        });
193
194
        return implode($delimiter, $row) . PHP_EOL;
195
    }
196
}
197