Failed Conditions
Pull Request — develop_3.0 (#434)
by Hura
03:16
created

WorkbookManagerAbstract::close()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Box\Spout\Writer\Common\Manager;
4
5
use Box\Spout\Common\Exception\IOException;
6
use Box\Spout\Writer\Common\Helper\FileSystemWithRootFolderHelperInterface;
7
use Box\Spout\Writer\Common\Entity\Options;
8
use Box\Spout\Writer\Common\Manager\Style\StyleManagerInterface;
9
use Box\Spout\Writer\Common\Entity\Row;
10
use Box\Spout\Writer\Common\Entity\Sheet;
11
use Box\Spout\Writer\Common\Entity\Workbook;
12
use Box\Spout\Writer\Common\Entity\Worksheet;
13
use Box\Spout\Writer\Exception\SheetNotFoundException;
14
use Box\Spout\Writer\Exception\WriterException;
15
use Box\Spout\Writer\Common\Creator\EntityFactory;
16
17
/**
18
 * Class WorkbookManagerAbstract
19
 * Abstract workbook manager, providing the generic interfaces to work with workbook.
20
 *
21
 * @package Box\Spout\Writer\Common\Manager
22
 */
23
abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
24
{
25
    /** @var Workbook The workbook to manage */
26
    protected $workbook;
27
28
    /** @var OptionsManagerInterface */
29
    protected $optionManager;
30
31
    /** @var WorksheetManagerInterface */
32
    protected $worksheetManager;
33
34
    /** @var StyleManagerInterface Manages styles */
35
    protected $styleManager;
36
37
    /** @var FileSystemWithRootFolderHelperInterface Helper to perform file system operations */
38
    protected $fileSystemHelper;
39
40
    /** @var EntityFactory Factory to create entities */
41
    protected $entityFactory;
42
43
    /** @var Worksheet The worksheet where data will be written to */
44
    protected $currentWorksheet;
45
46
47
    /**
48
     * @param Workbook $workbook
49
     * @param OptionsManagerInterface $optionsManager
50
     * @param WorksheetManagerInterface $worksheetManager
51
     * @param StyleManagerInterface $styleManager
52
     * @param FileSystemWithRootFolderHelperInterface $fileSystemHelper
53
     * @param EntityFactory $entityFactory
54
     */
55 78
    public function __construct(
56
        Workbook $workbook,
57
        OptionsManagerInterface $optionsManager,
58
        WorksheetManagerInterface $worksheetManager,
59
        StyleManagerInterface $styleManager,
60
        FileSystemWithRootFolderHelperInterface $fileSystemHelper,
61
        EntityFactory $entityFactory)
62
    {
63 78
        $this->workbook = $workbook;
64 78
        $this->optionManager = $optionsManager;
65 78
        $this->worksheetManager = $worksheetManager;
66 78
        $this->styleManager = $styleManager;
67 78
        $this->fileSystemHelper = $fileSystemHelper;
68 78
        $this->entityFactory = $entityFactory;
69 78
    }
70
71
    /**
72
     * @return int Maximum number of rows/columns a sheet can contain
73
     */
74
    abstract protected function getMaxRowsPerWorksheet();
75
76
    /**
77
     * @param Sheet $sheet
78
     * @return string The file path where the data for the given sheet will be stored
79
     */
80
    abstract protected function getWorksheetFilePath(Sheet $sheet);
81
82
    /**
83
     * @return Workbook
84
     */
85 8
    public function getWorkbook()
86
    {
87 8
        return $this->workbook;
88
    }
89
90
    /**
91
     * Creates a new sheet in the workbook and make it the current sheet.
92
     * The writing will resume where it stopped (i.e. data won't be truncated).
93
     *
94
     * @return Worksheet The created sheet
95
     * @throws IOException If unable to open the sheet for writing
96
     */
97 78
    public function addNewSheetAndMakeItCurrent()
98
    {
99 78
        $worksheet = $this->addNewSheet();
100 78
        $this->setCurrentWorksheet($worksheet);
101
102 78
        return $worksheet;
103
    }
104
105
    /**
106
     * Creates a new sheet in the workbook. The current sheet remains unchanged.
107
     *
108
     * @return Worksheet The created sheet
109
     * @throws \Box\Spout\Common\Exception\IOException If unable to open the sheet for writing
110
     */
111 78
    private function addNewSheet()
112
    {
113 78
        $worksheets = $this->getWorksheets();
114
115 78
        $newSheetIndex = count($worksheets);
116 78
        $sheet = $this->entityFactory->createSheet($newSheetIndex, $this->workbook->getInternalId());
117
118 78
        $worksheetFilePath = $this->getWorksheetFilePath($sheet);
119 78
        $worksheet = $this->entityFactory->createWorksheet($worksheetFilePath, $sheet);
120
121 78
        $this->worksheetManager->startSheet($worksheet);
122
123 78
        $worksheets[] = $worksheet;
124 78
        $this->workbook->setWorksheets($worksheets);
125
126 78
        return $worksheet;
127
    }
128
129
    /**
130
     * @return Worksheet[] All the workbook's sheets
131
     */
132 78
    public function getWorksheets()
133
    {
134 78
        return $this->workbook->getWorksheets();
135
    }
136
137
    /**
138
     * Returns the current sheet
139
     *
140
     * @return Worksheet The current sheet
141
     */
142 8
    public function getCurrentWorksheet()
143
    {
144 8
        return $this->currentWorksheet;
145
    }
146
147
    /**
148
     * Sets the given sheet as the current one. New data will be written to this sheet.
149
     * The writing will resume where it stopped (i.e. data won't be truncated).
150
     *
151
     * @param Sheet $sheet The "external" sheet to set as current
152
     * @return void
153
     * @throws SheetNotFoundException If the given sheet does not exist in the workbook
154
     */
155 2
    public function setCurrentSheet(Sheet $sheet)
156
    {
157 2
        $worksheet = $this->getWorksheetFromExternalSheet($sheet);
158 2
        if ($worksheet !== null) {
159 2
            $this->currentWorksheet = $worksheet;
160
        } else {
161
            throw new SheetNotFoundException('The given sheet does not exist in the workbook.');
162
        }
163 2
    }
164
165
    /**
166
     * @param Worksheet $worksheet
167
     * @return void
168
     */
169 78
    private function setCurrentWorksheet($worksheet)
170
    {
171 78
        $this->currentWorksheet = $worksheet;
172 78
    }
173
174
    /**
175
     * Returns the worksheet associated to the given external sheet.
176
     *
177
     * @param Sheet $sheet
178
     * @return Worksheet|null The worksheet associated to the given external sheet or null if not found.
179
     */
180 2
    private function getWorksheetFromExternalSheet($sheet)
181
    {
182 2
        $worksheetFound = null;
183
184 2
        foreach ($this->getWorksheets() as $worksheet) {
185 2
            if ($worksheet->getExternalSheet() === $sheet) {
186 2
                $worksheetFound = $worksheet;
187 2
                break;
188
            }
189
        }
190
191 2
        return $worksheetFound;
192
    }
193
194
    /**
195
     * Adds a row to the current sheet.
196
     * If shouldCreateNewSheetsAutomatically option is set to true, it will handle pagination
197
     * with the creation of new worksheets if one worksheet has reached its maximum capicity.
198
     *
199
     * @param Row $row The row to added
200
     * @return void
201
     * @throws IOException If trying to create a new sheet and unable to open the sheet for writing
202
     * @throws WriterException If unable to write data
203
     */
204
    public function addRowToCurrentWorksheet(Row $row)
205
    {
206
        $currentWorksheet = $this->getCurrentWorksheet();
207
        $hasReachedMaxRows = $this->hasCurrentWorksheetReachedMaxRows();
208
209
        // if we reached the maximum number of rows for the current sheet...
210
        if ($hasReachedMaxRows) {
211
            // ... continue writing in a new sheet if option set
212
            if ($this->optionManager->getOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY)) {
213
                $currentWorksheet = $this->addNewSheetAndMakeItCurrent();
214
215
                $this->addRowToWorksheet($currentWorksheet, $row);
216
            } else {
217
                // otherwise, do nothing as the data won't be written anyways
218
            }
219
        } else {
220
            $this->addRowToWorksheet($currentWorksheet, $row);
221
        }
222
    }
223
224
    /**
225
     * @return bool Whether the current worksheet has reached the maximum number of rows per sheet.
226
     */
227
    private function hasCurrentWorksheetReachedMaxRows()
228
    {
229
        $currentWorksheet = $this->getCurrentWorksheet();
230
        return ($currentWorksheet->getLastWrittenRowIndex() >= $this->getMaxRowsPerWorksheet());
231
    }
232
233
    /**
234
     * Adds data with the given style to the given sheet.
235
     *
236
     * @param Worksheet $worksheet Worksheet to write the row to
237
     * @param Row $row The row to be added
238
     * @return void
239
     * @throws WriterException If unable to write data
240
     */
241
    private function addRowToWorksheet(Worksheet $worksheet, Row $row)
242
    {
243
        $this->worksheetManager->addRow($worksheet, $row);
244
245
        // update max num columns for the worksheet
246
        $currentMaxNumColumns = $worksheet->getMaxNumColumns();
247
        $cellsCount = count($row->getCells());
248
        $worksheet->setMaxNumColumns(max($currentMaxNumColumns, $cellsCount));
249
    }
250
251
    /**
252
     * Closes the workbook and all its associated sheets.
253
     * All the necessary files are written to disk and zipped together to create the final file.
254
     * All the temporary files are then deleted.
255
     *
256
     * @param resource $finalFilePointer Pointer to the spreadsheet that will be created
257
     * @return void
258
     */
259 8
    public function close($finalFilePointer)
260
    {
261 8
        $this->closeAllWorksheets();
262 8
        $this->closeRemainingObjects();
263 8
        $this->writeAllFilesToDiskAndZipThem($finalFilePointer);
264 8
        $this->cleanupTempFolder();
265 8
    }
266
267
    /**
268
     * Closes custom objects that are still opened
269
     *
270
     * @return void
271
     */
272 4
    protected function closeRemainingObjects()
273
    {
274
        // do nothing by default
275 4
    }
276
277
    /**
278
     * Writes all the necessary files to disk and zip them together to create the final file.
279
     *
280
     * @param resource $finalFilePointer Pointer to the spreadsheet that will be created
281
     * @return void
282
     */
283
    abstract protected function writeAllFilesToDiskAndZipThem($finalFilePointer);
284
285
    /**
286
     * Closes all workbook's associated sheets.
287
     *
288
     * @return void
289
     */
290 8
    private function closeAllWorksheets()
291
    {
292 8
        $worksheets = $this->getWorksheets();
293
294 8
        foreach ($worksheets as $worksheet) {
295 8
            $this->worksheetManager->close($worksheet);
296
        }
297 8
    }
298
299
    /**
300
     * Deletes the root folder created in the temp folder and all its contents.
301
     *
302
     * @return void
303
     */
304 8
    protected function cleanupTempFolder()
305
    {
306 8
        $rootFolder = $this->fileSystemHelper->getRootFolder();
307 8
        $this->fileSystemHelper->deleteFolderRecursively($rootFolder);
308 8
    }
309
}
310