Passed
Branch master (eee465)
by ma
03:18
created

GroupHandler::processGroupLeft()   C

Complexity

Conditions 13
Paths 24

Size

Total Lines 72
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 37
c 0
b 0
f 0
nc 24
nop 8
dl 0
loc 72
rs 6.6166

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @name: GroupHandler
4
 * @author: JiaMeng <[email protected]>
5
 * @file: GroupHandler.php
6
 * @Date: 2025/01/XX
7
 */
8
namespace tinymeng\spreadsheet\Excel\Handler;
9
10
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
11
use tinymeng\spreadsheet\Util\WorkSheetHelper;
12
use tinymeng\tools\exception\StatusCode;
13
use tinymeng\tools\exception\TinymengException;
14
15
class GroupHandler
16
{
17
    /**
18
     * 处理左侧分组数据
19
     * @param Worksheet $worksheet
20
     * @param array $data 分组后的数据
21
     * @param int $groupLeftCount 分组级别数
22
     * @param array $groupLeft 分组字段列表
23
     * @param array $fields 所有字段列表
24
     * @param array $mergeColumns 需要合并的列
25
     * @param int $row 当前行
26
     * @param callable $setCellValueFunc 设置单元格值的函数(用于递归调用)
27
     * @return int 返回更新后的行号
28
     */
29
    public static function processGroupLeft(
30
        Worksheet $worksheet,
31
        array $data,
32
        int $groupLeftCount,
33
        array $groupLeft,
34
        array $fields,
35
        array $mergeColumns,
36
        int $row,
37
        callable $setCellValueFunc
38
    ): int {
39
        // 获取分组字段在field中的实际位置
40
        $group_field_positions = [];
41
        foreach ($groupLeft as $group_field) {
42
            $position = array_search($group_field, $fields);
43
            if ($position !== false) {
44
                $group_field_positions[] = $position;
45
            }
46
        }
47
48
        if (empty($group_field_positions)) {
49
            throw new TinymengException(StatusCode::COMMON_PARAM_INVALID, '分组字段未在标题中定义');
50
        }
51
52
        $group_start = $row;
53
        foreach ($data as $key => $val) {
54
            // 第一级分组的合并单元格
55
            $rowName = WorkSheetHelper::cellName($group_field_positions[0]); // 使用第一个分组字段的实际位置
56
            $coordinate = $rowName . $row . ':' . $rowName . ($row + $val['count'] - 1);
57
            $worksheet->mergeCells($coordinate);
58
            $worksheet->setCellValue($rowName . $row, $key);
59
60
            // 合并mergeColumns指定的其它列
61
            if (!empty($mergeColumns)) {
62
                foreach ($mergeColumns as $field) {
63
                    // 跳过分组字段本身
64
                    if (in_array($field, $groupLeft)) continue;
65
                    $colIdx = array_search($field, $fields);
66
                    if ($colIdx !== false) {
67
                        $colLetter = WorkSheetHelper::cellName($colIdx);
0 ignored issues
show
Bug introduced by
It seems like $colIdx can also be of type string; however, parameter $columnIndex of tinymeng\spreadsheet\Uti...SheetHelper::cellName() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

67
                        $colLetter = WorkSheetHelper::cellName(/** @scrutinizer ignore-type */ $colIdx);
Loading history...
68
                        $worksheet->mergeCells($colLetter . $row . ':' . $colLetter . ($row + $val['count'] - 1));
69
                        // 取本组第一个数据的值
70
                        $worksheet->setCellValue($colLetter . $row, $val['data'][0][$field] ?? '');
71
                    }
72
                }
73
            }
74
75
            if ($groupLeftCount == 1) {
76
                foreach ($val['data'] as $dataRow) {
77
                    $setCellValueFunc($dataRow);
78
                }
79
            } else {
80
                $sub_group_start = $row;
81
                $rowName = WorkSheetHelper::cellName($group_field_positions[1]); // 使用第二个分组字段的实际位置
82
83
                foreach ($val['data'] as $k => $v) {
84
                    $coordinate = $rowName . $sub_group_start . ':' . $rowName . ($sub_group_start + $v['count'] - 1);
85
                    $worksheet->mergeCells($coordinate);
86
                    $worksheet->setCellValue($rowName . $sub_group_start, $k);
87
88
                    foreach ($v['data'] as $data) {
89
                        $setCellValueFunc($data);
90
                    }
91
92
                    $sub_group_start = $sub_group_start + $v['count'];
93
                }
94
            }
95
96
            $row = $group_start + $val['count'];
97
            $group_start = $row;
98
        }
99
        
100
        return $row;
101
    }
102
103
    /**
104
     * 数据分组(一级分组)
105
     * @param array $data 原始数据
106
     * @param string $groupField 分组字段
107
     * @return array
108
     */
109
    public static function groupDataByOneField(array $data, string $groupField): array
110
    {
111
        $grouped = [];
112
        foreach ($data as $k => $v) {
113
            if (isset($v[$groupField])) {
114
                $grouped[$v[$groupField]][] = $v;
115
            }
116
        }
117
        foreach ($grouped as $k => $v) {
118
            $grouped[$k] = [
119
                'data' => $v,
120
                'count' => count($v)
121
            ];
122
        }
123
        return $grouped;
124
    }
125
126
    /**
127
     * 数据分组(二级分组)
128
     * @param array $data 原始数据
129
     * @param string $firstGroupField 第一级分组字段
130
     * @param string $secondGroupField 第二级分组字段
131
     * @return array
132
     */
133
    public static function groupDataByTwoFields(array $data, string $firstGroupField, string $secondGroupField): array
134
    {
135
        $grouped = [];
136
        foreach ($data as $v) {
137
            if (isset($v[$firstGroupField]) && isset($v[$secondGroupField])) {
138
                $grouped[$v[$firstGroupField]][$v[$secondGroupField]][] = $v;
139
            }
140
        }
141
        return self::arrayCount($grouped);
142
    }
143
144
    /**
145
     * 二位数组获取每一级别数量
146
     * @param array $data 二维数组原始数据
147
     * @return array
148
     */
149
    private static function arrayCount(array $data): array
150
    {
151
        foreach ($data as $key => $val) {
152
            $num = 0;
153
            foreach ($val as $k => $v) {
154
                $sub_num = count($v);
155
                $num = $num + $sub_num;
156
                $val[$k] = [
157
                    'count' => $sub_num,
158
                    'data' => $v
159
                ];
160
            }
161
            $data[$key] = [
162
                'count' => $num,
163
                'data' => $val
164
            ];
165
        }
166
        return $data;
167
    }
168
}
169
170