Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
17 / 17
CRAP
100.00% covered (success)
100.00%
115 / 115
GoogleSheetsService
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
17 / 17
41
100.00% covered (success)
100.00%
115 / 115
 spreadsheet
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 sheet
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 newSheet
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
9 / 9
 createSheet
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 createRow
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
6 / 6
 createCell
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 range
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 all
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
16 / 16
 sheetList
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 deleteSheet
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 query
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 ranges
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
8 / 8
 append
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
8 / 8
 orderAppendables
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
16 / 16
 first
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 spreadsheetByTitle
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
6 / 6
 save
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
13 / 13
1<?php
2
3namespace Qmp\Laravel\GoogleApiWrapper\Services;
4
5use Exception;
6use Illuminate\Support\Arr;
7use Google\Service\Sheets;
8use Google\Service\Sheets\{
9    Sheet,
10    Spreadsheet,
11    ValueRange,
12    GridData,
13    SheetProperties,
14    RowData,
15    CellData,
16    ExtendedValue,
17    BatchUpdateSpreadsheetRequest,
18    AppendValuesResponse
19};
20
21class GoogleSheetsService extends GoogleBaseService
22{
23
24    /**
25     * Undocumented variable
26     *
27     * @var string
28     */
29    protected $serviceClass = Sheets::class;
30
31    /**
32     * Undocumented variable
33     *
34     * @var array
35     */
36    protected $newSheets = [];
37
38    /**
39     * Undocumented variable
40     *
41     * @var string
42     */
43    protected $spreadsheetId;
44
45    /**
46     * Undocumented variable
47     *
48     * @var string
49     */
50    protected $sheet = '';
51
52    /**
53     * Undocumented variable
54     *
55     * @var string
56     */
57    protected $range = '';
58
59    /**
60     * Undocumented function
61     *
62     * @return self
63     */
64    public function spreadsheet(string $fileId)
65    {
66        $this->setOption('fileId', $fileId);
67        return $this;
68    }
69
70    /**
71     * Undocumented function
72     *
73     * @param string|array $sheet
74     * @return self
75     */
76    public function sheet($sheet)
77    {
78        $this->sheet = $sheet;
79        return $this;
80    }
81
82    /**
83     * Undocumented function
84     *
85     * @param string $title
86     * @return void
87     */
88    public function newSheet($title, $data): self
89    {
90        $sheet = $this->createSheet($title);
91        $gridData = new GridData;
92        $rows = [];
93
94        foreach ($data as $datum) {
95            $rows[] = $this->createRow($datum);
96        }
97
98        $gridData->setRowData($rows);
99        $sheet->setData($gridData);
100
101        $this->newSheets[$title] = $sheet;
102
103        return $this;
104    }
105
106    /**
107     * Undocumented function
108     *
109     * @param string $title
110     * @return Sheet
111     */
112    protected function createSheet(string $title): Sheet
113    {
114        $sheet = new Sheet;
115        $sheetProperties = new SheetProperties;
116        $sheetProperties->setTitle($title);
117        $sheet->setProperties($sheetProperties);
118
119        return $sheet;
120    }
121
122    /**
123     * Undocumented function
124     *
125     * @param array $cells
126     * @return RowData
127     */
128    protected function createRow(array $cells): RowData
129    {
130
131        $rowCell = [];
132        $row = new RowData;
133
134        foreach ($cells as $cell) {
135            $rowCell[] = $this->createCell($cell);
136        }
137
138        $row->setValues($rowCell);
139
140        return $row;
141    }
142
143
144    /**
145     * Undocumented function
146     *
147     * @param string $value
148     * @return Google_Service_Sheets_CellData
149     */
150    protected function createCell(string $value): CellData
151    {
152        $cell = new CellData;
153        $extendedValue = new ExtendedValue;
154        $extendedValue->setStringValue($value);
155        $cell->setUserEnteredValue($extendedValue);
156
157        return $cell;
158    }
159
160
161    /**
162     * Undocumented function
163     *
164     * @param string $sheet
165     * @return self
166     */
167    public function range(string $range)
168    {
169        $this->range = $range;
170        return $this;
171    }
172
173    /**
174     * Undocumented function
175     *
176     * @return array
177     */
178    public function all(): array
179    {
180        $forceKey = false;
181
182        if (!$this->getOption('fileId')) {
183            throw new Exception("Spreadsheet id must be set !");
184        }
185
186        if (!$this->sheet) {
187            $this->sheet = array_values($this->sheetList());
188            $forceKey = true;
189        }
190
191        $query = $this->query();
192        $sheets = $this->service->spreadsheets_values->batchGet($this->getOption('fileId'), $query);
193        $values = $sheets->getValueRanges();
194
195
196        if (count($values) > 1 || $forceKey) {
197            $arr = [];
198            foreach ($values as $value) {
199                $key = str_replace("'", "", explode("!", $value->getRange())[0]);
200                $arr[$key] = $value->getValues();
201            }
202
203            return $arr;
204        }
205
206        return $values ? $values[0]->getValues() : [];
207    }
208
209    /**
210     * @return array
211     */
212    public function sheetList(): array
213    {
214        $list = [];
215        $sheets = $this->service->spreadsheets->get($this->getOption('fileId'))->getSheets();
216        foreach ($sheets as $sheet) {
217            $list[$sheet->getProperties()->getSheetId()] = $sheet->getProperties()->getTitle();
218        }
219        return $list;
220    }
221
222    /**
223     * @param  string  $sheetTitle
224     *
225     * @return BatchUpdateSpreadsheetRequest
226     */
227    public function deleteSheet(string $sheetTitle)
228    {
229        $list = $this->sheetList();
230        $id = Arr::get(array_flip($list), $sheetTitle);
231
232        $body = new BatchUpdateSpreadsheetRequest(
233            [
234                'requests' => [
235                    'deleteSheet' => [
236                        'sheetId' => $id,
237                    ],
238                ],
239            ]
240        );
241
242        return $this->service->spreadsheets->batchUpdate($this->getOption('fileId'), $body);
243    }
244
245    /**
246     * Undocumented function
247     *
248     * @return array
249     */
250    protected function query(): array
251    {
252        $query = [];
253        $ranges = $this->ranges();
254        if (!empty($ranges)) {
255            $query['ranges'] = $ranges;
256        }
257
258        return $query;
259    }
260
261    /**
262     * Undocumented function
263     *
264     * @return string|array
265     */
266    protected function ranges()
267    {
268        if (blank($this->range)) {
269            return $this->sheet;
270        }
271
272        if (is_array($this->sheet)) {
273            $arr = [];
274            foreach ($this->sheet as $sheet) {
275                $arr[] = $sheet . '!' . $this->range;
276            }
277            return $arr;
278        }
279
280        return $this->sheet . '!' . $this->range;
281    }
282
283    /**
284     * @param  array  $values
285     * @param  string  $valueInputOption
286     * @param  string  $insertDataOption
287     *
288     * @return mixed|AppendValuesResponse
289     */
290    public function append(array $values, string $valueInputOption = 'RAW', string $insertDataOption = 'OVERWRITE')
291    {
292        $range = $this->ranges();
293        $orderedValues = $this->orderAppendables($values);
294
295        $valueRange = new ValueRange();
296        $valueRange->setValues($orderedValues);
297        $valueRange->setRange($range);
298
299        $optParams = [
300            'valueInputOption' => $valueInputOption,
301            'insertDataOption' => $insertDataOption,
302        ];
303
304        return $this->service->spreadsheets_values->append($this->getOption('fileId'), $range, $valueRange, $optParams);
305    }
306
307    /**
308     * @param  array  $values
309     * @return array
310     */
311    public function orderAppendables(array $values)
312    {
313        if (!Arr::isAssoc(head($values) ?: [])) {
314            return $values;
315        }
316
317        $header = $this->first();
318
319        $ordered = [];
320        foreach ($values as $value) {
321            array_push(
322                $ordered,
323                array_values(array_replace(array_flip($header), $value))
324            );
325        }
326
327        return array_map(function ($row) {
328            $notNull = [];
329            foreach ($row as $key => $value) {
330                if (is_null($value) || $key === $value) {
331                    array_push($notNull, '');
332                } else {
333                    array_push($notNull, $value);
334                }
335            }
336
337            return $notNull;
338        }, $ordered);
339    }
340
341
342    /**
343     * Undocumented function
344     *
345     * @return array
346     */
347    public function first(): array
348    {
349        $values = $this->all();
350        return $values[array_key_first($values)] ?: [];
351    }
352
353    /**
354     * @param  string  $title
355     * @return $this
356     */
357    public function spreadsheetByTitle(string $title)
358    {
359        $list = $this->service('drive')->listFiles('sheet');
360        $id = Arr::get(array_flip($list), $title);
361
362        if (!$id) {
363            throw new Exception("Spreadsheet '$title' not found !");
364        }
365
366        $this->setOption('fileId', $id);
367
368        return $this;
369    }
370
371    /**
372     * Undocumented function
373     *
374     * @param mixed $file
375     * @param mixed $data
376     * @return self
377     */
378    public function save($title)
379    {
380        $file = new Spreadsheet([
381            'properties' => [
382                'title' => $title
383            ]
384        ]);
385
386        if ($this->newSheets) {
387            $file->setSheets($this->newSheets ? array_values($this->newSheets) : []);
388
389            $spreadsheet = $this->service->spreadsheets->create($file, [
390                'fields' => 'spreadsheetId'
391            ]);
392
393            $this->setOption('fileId', $spreadsheet->spreadsheetId);
394            $this->sheet = $this->newSheets[array_key_first($this->newSheets)]->getProperties()->getTitle();
395
396            if ($this->getOption('permission')) {
397                $this->service('drive')->setPermission();
398            }
399
400            $this->newSheets = [];
401            return $spreadsheet;
402        }
403        throw new Exception("Create Spreasheet first !");
404    }
405}