Sheet::export()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 7
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of the bugloos/export-bundle project.
5
 * (c) Bugloos <https://bugloos.com/>
6
 * For the full copyright and license information, please view
7
 * the LICENSE file that was distributed with this source code.
8
 */
9
10
namespace Bugloos\ExportBundle;
11
12
use Bugloos\ExportBundle\Contracts\ColumnFormattingInterface;
13
use Bugloos\ExportBundle\Contracts\ColumnWidthsInterface;
14
use Bugloos\ExportBundle\Contracts\CustomStartCellInterface;
15
use Bugloos\ExportBundle\Contracts\ShouldAutoSizeInterface;
16
use Bugloos\ExportBundle\Contracts\StylesInterface;
17
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
18
19
/**
20
 * @author Mojtaba Gheytasi <[email protected] | [email protected]>
21
 */
22
class Sheet
23
{
24
    private Worksheet $worksheet;
25
26
    private object $exportable;
27
28
    public function __construct(Worksheet $worksheet)
29
    {
30
        $this->worksheet = $worksheet;
31
    }
32
33
    public function export($sheetExport)
34
    {
35
        $this->open($sheetExport);
36
37
        $this->fromCollection($sheetExport);
38
39
        $this->close($sheetExport);
40
    }
41
42
    public function disconnect()
43
    {
44
        $this->worksheet->disconnectCells();
45
        unset($this->worksheet);
46
    }
47
48
    private function open($sheetExport)
49
    {
50
        $this->exportable = $sheetExport;
51
52
        $this->worksheet->setTitle($sheetExport->title());
53
54
        $startCell = $sheetExport instanceof CustomStartCellInterface ?
55
            $sheetExport->startCell() : null;
56
57
        $this->append($sheetExport->headings(), $startCell);
58
    }
59
60
    private function fromCollection($sheetExport)
61
    {
62
        $this->appendRows($sheetExport->collection(), $sheetExport);
63
    }
64
65
    private function appendRows(iterable $rows, $sheetExport)
66
    {
67
        $rows = array_map(function ($row) use ($sheetExport) {
68
            return $sheetExport->map($row);
69
        }, $rows);
0 ignored issues
show
Bug introduced by
$rows of type iterable is incompatible with the type array expected by parameter $array of array_map(). ( Ignorable by Annotation )

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

69
        }, /** @scrutinizer ignore-type */ $rows);
Loading history...
70
71
        $startCell = $sheetExport instanceof CustomStartCellInterface ?
72
            $sheetExport->startCell() : null;
73
74
        $this->append($rows, $startCell);
75
    }
76
77
    private function append(array $rows, string $startCell = null)
78
    {
79
        if (null === $startCell) {
80
            $startCell = 'A1';
81
        }
82
83
        if ($this->hasRows()) {
84
            $startCell = self::getColumnFromCoordinate($startCell).($this->worksheet->getHighestRow() + 1);
85
        }
86
87
        $this->worksheet->fromArray($rows, null, $startCell);
88
    }
89
90
    private function hasRows(): bool
91
    {
92
        $startCell = 'A1';
93
94
        if ($this->exportable instanceof CustomStartCellInterface) {
95
            $startCell = $this->exportable->startCell();
96
        }
97
98
        return $this->worksheet->cellExists($startCell);
99
    }
100
101
    private function close($sheetExport)
102
    {
103
        $this->exportable = $sheetExport;
104
105
        if ($sheetExport instanceof ColumnFormattingInterface) {
106
            foreach ($sheetExport->columnFormats() as $column => $format) {
107
                $this->formatColumn($column, $format);
108
            }
109
        }
110
111
        if ($sheetExport instanceof ShouldAutoSizeInterface) {
112
            $this->autoSize();
113
        }
114
115
        if ($sheetExport instanceof ColumnWidthsInterface) {
116
            foreach ($sheetExport->columnWidths() as $column => $width) {
117
                $this->worksheet->getColumnDimension($column)
118
                    ->setAutoSize(false)
119
                    ->setWidth($width)
120
                ;
121
            }
122
        }
123
124
        if ($sheetExport instanceof StylesInterface) {
125
            $styles = $sheetExport->styles($this->worksheet);
126
127
            if (\is_array($styles)) {
128
                foreach ($styles as $coordinate => $coordinateStyles) {
129
                    if (is_numeric($coordinate)) {
130
                        $coordinate = 'A'.$coordinate.':'.$this->worksheet->getHighestColumn($coordinate).$coordinate;
131
                    }
132
133
                    $this->worksheet->getStyle($coordinate)->applyFromArray($coordinateStyles);
134
                }
135
            }
136
        }
137
    }
138
139
    private function autoSize()
140
    {
141
        foreach ($this->buildColumnRange('A', $this->worksheet->getHighestDataColumn()) as $col) {
142
            $dimension = $this->worksheet->getColumnDimension($col);
143
144
            if (-1 == $dimension->getWidth()) {
145
                $dimension->setAutoSize(true);
146
            }
147
        }
148
    }
149
150
    private function buildColumnRange(string $lower, string $upper): \Generator
151
    {
152
        ++$upper;
153
154
        for ($i = $lower; $i !== $upper; ++$i) {
155
            yield $i;
156
        }
157
    }
158
159
    private function formatColumn(string $column, string $format)
160
    {
161
        $this->worksheet
162
            ->getStyle($column.'1:'.$column.$this->worksheet->getHighestRow())
163
            ->getNumberFormat()
164
            ->setFormatCode($format)
165
        ;
166
    }
167
168
    private static function getColumnFromCoordinate(string $coordinate): string
169
    {
170
        return preg_replace('/[0-9]/', '', $coordinate);
171
    }
172
}
173