• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

miaoxing / services / 6801533350

08 Nov 2023 04:34PM UTC coverage: 10.534% (-0.8%) from 11.327%
6801533350

push

github

twinh
ci: add PHP 8, remove PHP 7.2, 7.3

69 of 655 relevant lines covered (10.53%)

2.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

1.19
/src/Service/IndexAction.php
1
<?php
2

3
namespace Miaoxing\Services\Service;
4

5
use Miaoxing\Plugin\BaseModel;
6
use Miaoxing\Services\Action\BaseAction;
7
use PhpOffice\PhpSpreadsheet\Cell\DataType;
8
use PhpOffice\PhpSpreadsheet\Spreadsheet;
9
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
10
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
11
use Wei\BaseController;
12
use Wei\Req;
13

14
class IndexAction extends BaseAction
15
{
16
    /**
17
     * Change number more than 12 characters to string, because excel displays it in scientific notation
18
     *
19
     * @internal
20
     */
21
    protected const MAX_NUMBER_LENGTH = 12;
22

23
    /**
24
     * @var string|null
25
     */
26
    protected $name;
27

28
    /**
29
     * @var array
30
     */
31
    protected $columns = [];
32

33
    /**
34
     * @var int
35
     */
36
    protected $maxLimit = 10000;
37

38
    /**
39
     * @param BaseController $controller
40
     * @return mixed
41
     * @svc
42
     */
43
    protected function exec(BaseController $controller)
44
    {
45
        // 1. 构建查询
46
        $models = $this->convention->createModel($controller);
×
47
        $models->setReq($this->req);
×
48

49
        $this->triggerRet('beforeFind', [$models, $this->req]);
×
50

51
        $this->triggerRet('beforeReqQuery', [$models, $this->req]);
×
52

53
        $include = $controller->getOption('include');
×
54
        $models->setReqRelations($include ?: [])->reqQuery();
×
55

56
        $this->isExport() && $models->limit($this->maxLimit);
×
57
        $this->triggerRet('afterReqQuery', [$models, $this->req]);
×
58

59
        $models->all();
×
60
        $this->trigger('afterFind', [$models, $this->req]);
×
61

62
        $this->includeModel($controller, $models);
×
63

64
        // 2. 组装返回数据
65
        if ($this->isExport()) {
×
66
            $this->responseXlsx($models);
×
67
            return;
×
68
        }
69
        return $this->responseRet($models);
×
70
    }
71

72
    public function getName(): ?string
73
    {
74
        return $this->name;
×
75
    }
76

77
    public function setName(string $name): self
78
    {
79
        $this->name = $name;
×
80
        return $this;
×
81
    }
82

83
    public function getColumns(): array
84
    {
85
        return $this->columns;
×
86
    }
87

88
    public function setColumns(array $columns): self
89
    {
90
        $this->columns = $columns;
×
91
        return $this;
×
92
    }
93

94
    public function getMaxLimit(): int
95
    {
96
        return $this->maxLimit;
×
97
    }
98

99
    public function setMaxLimit(int $maxLimit): self
100
    {
101
        $this->maxLimit = $maxLimit;
×
102
        return $this;
×
103
    }
104

105
    protected function responseFormat($models)
106
    {
107
        switch ($this->req['format']) {
×
108
            case 'xlsx':
×
109
                $this->responseXlsx($models);
×
110
                return;
×
111

112
            default:
113
                return $this->responseRet($models);
×
114
        }
115
    }
116

117
    /**
118
     * @param callable $callable
119
     * @return $this
120
     * @svc
121
     */
122
    protected function beforeReqQuery(callable $callable)
123
    {
124
        return $this->on(__FUNCTION__, $callable);
×
125
    }
126

127
    /**
128
     * @param callable $callable
129
     * @return $this
130
     * @svc
131
     */
132
    protected function afterReqQuery(callable $callable)
133
    {
134
        return $this->on(__FUNCTION__, $callable);
×
135
    }
136

137
    /**
138
     * @param callable $callable
139
     * @return $this
140
     * @svc
141
     */
142
    protected function beforeFind(callable $callable)
143
    {
144
        return $this->on(__FUNCTION__, $callable);
×
145
    }
146

147
    /**
148
     * @param callable $callable
149
     * @return $this
150
     * @svc
151
     */
152
    protected function afterFind(callable $callable)
153
    {
154
        return $this->on(__FUNCTION__, $callable);
1✔
155
    }
156

157
    /**
158
     * @param callable $callable
159
     * @return $this
160
     * @svc
161
     */
162
    protected function buildData(callable $callable)
163
    {
164
        return $this->on(__FUNCTION__, $callable);
×
165
    }
166

167
    /**
168
     * @param callable $callable
169
     * @return $this
170
     * @svc
171
     */
172
    protected function buildRet(callable $callable)
173
    {
174
        return $this->on(__FUNCTION__, $callable);
×
175
    }
176

177
    protected function triggerBuildData($model)
178
    {
179
        return $this->trigger('buildData', [$model]) ?: [];
×
180
    }
181

182
    protected function triggerBuildRet($ret, BaseModel $models, Req $req)
183
    {
184
        return $this->trigger('buildRet', [$ret, $models, $req]) ?: $ret;
×
185
    }
186

187
    protected function includeModel(BaseController $controller, BaseModel $models)
188
    {
189
        $models->load($controller->getOption('include'));
×
190
    }
191

192
    /**
193
     * @param BaseModel|BaseModel[] $models
194
     */
195
    protected function responseRet(BaseModel $models)
196
    {
197
        $data = [];
×
198
        /** @var BaseModel $model */
199
        foreach ($models as $model) {
×
200
            $data[] = array_merge($model->toArray(), $this->triggerBuildData($model));
×
201
        }
202

203
        return $this->triggerBuildRet($models->toRet(['data' => $data]), $models, $this->req);
×
204
    }
205

206
    /**
207
     * @param BaseModel|BaseModel[] $models
208
     * @internal
209
     */
210
    protected function responseXlsx(BaseModel $models)
211
    {
212
        $spreadsheet = new Spreadsheet();
×
213
        $sheet = $spreadsheet->getActiveSheet();
×
214
        $startRow = '1';
×
215
        $startColumn = 'A';
×
216
        foreach ($this->columns as $column) {
×
217
            $sheet->setCellValue($startColumn . $startRow, $column['title']);
×
218
            ++$startColumn;
×
219
        }
220

221
        foreach ($models as $model) {
×
222
            ++$startRow;
×
223
            $startColumn = 'A';
×
224
            foreach ($this->columns as $column) {
×
225
                $this->setCellValue($sheet, $startColumn . $startRow, $this->getValue($model, $column));
×
226
                ++$startColumn;
×
227
            }
228
        }
229

230
        $fileName = $this->name . '-' . date('Y-m-d-H-i-s');
×
231
        $res = $this->res;
×
232
        $res->setHeader([
×
233
            'Content-type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
×
234
            'Content-Disposition' => 'attachment;filename=' . $fileName . '.xlsx',
×
235
            'Access-Control-Expose-Headers' => 'Content-Disposition',
×
236
        ]);
×
237
        $res->sendHeader();
×
238
        $writer = new Xlsx($spreadsheet);
×
239
        $writer->save('php://output');
×
240
    }
241

242
    /**
243
     * @return bool
244
     * @internal
245
     */
246
    protected function isExport(): bool
247
    {
248
        return 'xlsx' === $this->req['format'];
×
249
    }
250

251
    /**
252
     * @param mixed $model
253
     * @param mixed $column
254
     * @internal
255
     */
256
    protected function getValue($model, $column)
257
    {
258
        if (!isset($column['index'])) {
×
259
            $value = null;
×
260
        } elseif (is_string($column['index'])) {
×
261
            $value = $model->get($column['index']);
×
262
        } else {
263
            $value = $this->getValueByPaths($model, $column['index']);
×
264
        }
265

266
        if (isset($column['render'])) {
×
267
            return $column['render']($value, $model);
×
268
        }
269

270
        return $value;
×
271
    }
272

273
    /**
274
     * @internal
275
     */
276
    protected function getValueByPaths(BaseModel $value, array $paths)
277
    {
278
        foreach ($paths as $path) {
×
279
            $value = $value->get($path, $exists, false);
×
280
            if (!$exists) {
×
281
                return null;
×
282
            }
283
            if (!$value) {
×
284
                return $value;
×
285
            }
286
        }
287
        return $value;
×
288
    }
289

290
    /**
291
     * @param mixed $position
292
     * @param mixed $value
293
     * @internal
294
     */
295
    protected function setCellValue(Worksheet $sheet, $position, $value)
296
    {
297
        if (strlen($value) >= static::MAX_NUMBER_LENGTH && is_numeric($value)) {
×
298
            $sheet->setCellValueExplicit($position, $value, DataType::TYPE_STRING);
×
299
        } else {
300
            $sheet->setCellValue($position, $value);
×
301
        }
302
    }
303
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc