Completed
Pull Request — develop_3.0 (#431)
by Adrien
02:35
created

WorkbookManagerAbstract::cleanupTempFolder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
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\Helper\StyleHelperInterface;
8
use Box\Spout\Writer\Common\Entity\Options;
9
use Box\Spout\Writer\Common\Sheet;
10
use Box\Spout\Writer\Common\Entity\Workbook;
11
use Box\Spout\Writer\Common\Entity\Worksheet;
12
use Box\Spout\Writer\Exception\SheetNotFoundException;
13
use Box\Spout\Writer\Exception\WriterException;
14
use Box\Spout\Writer\Common\Creator\EntityFactory;
15
use Box\Spout\Writer\Style\Style;
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 StyleHelperInterface */
35
    protected $styleHelper;
36
37
    /** @var FileSystemWithRootFolderHelperInterface Helper to perform file system operations */
38
    protected $fileSystemHelper;
39
40
    /** @var EntityFactory Factory to create entities */
41
    private $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 StyleHelperInterface $styleHelper
52
     * @param FileSystemWithRootFolderHelperInterface $fileSystemHelper
53
     * @param EntityFactory $entityFactory
54
     */
55 89
    public function __construct(
56
        Workbook $workbook,
57
        OptionsManagerInterface $optionsManager,
58
        WorksheetManagerInterface $worksheetManager,
59
        StyleHelperInterface $styleHelper,
60
        FileSystemWithRootFolderHelperInterface $fileSystemHelper,
61
        EntityFactory $entityFactory)
62
    {
63 89
        $this->workbook = $workbook;
64 89
        $this->optionManager = $optionsManager;
65 89
        $this->worksheetManager = $worksheetManager;
66 89
        $this->styleHelper = $styleHelper;
67 89
        $this->fileSystemHelper = $fileSystemHelper;
68 89
        $this->entityFactory = $entityFactory;
69 89
    }
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 70
    public function getWorkbook()
86
    {
87 70
        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 89
    public function addNewSheetAndMakeItCurrent()
98
    {
99 89
        $worksheet = $this->addNewSheet();
100 89
        $this->setCurrentWorksheet($worksheet);
101
102 89
        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 89
    private function addNewSheet()
112
    {
113 89
        $worksheets = $this->getWorksheets();
114
115 89
        $newSheetIndex = count($worksheets);
116 89
        $sheet = new Sheet($newSheetIndex, $this->workbook->getInternalId());
117
118 89
        $worksheetFilePath = $this->getWorksheetFilePath($sheet);
119 89
        $worksheet = $this->entityFactory->createWorksheet($worksheetFilePath, $sheet);
120
121 89
        $this->worksheetManager->startSheet($worksheet);
122
123 89
        $worksheets[] = $worksheet;
124 89
        $this->workbook->setWorksheets($worksheets);
125
126 89
        return $worksheet;
127
    }
128
129
    /**
130
     * @return Worksheet[] All the workbook's sheets
131
     */
132 89
    public function getWorksheets()
133
    {
134 89
        return $this->workbook->getWorksheets();
135
    }
136
137
    /**
138
     * Returns the current sheet
139
     *
140
     * @return Worksheet The current sheet
141
     */
142 70
    public function getCurrentWorksheet()
143
    {
144 70
        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 4
    public function setCurrentSheet(Sheet $sheet)
156
    {
157 4
        $worksheet = $this->getWorksheetFromExternalSheet($sheet);
158 4
        if ($worksheet !== null) {
159 4
            $this->currentWorksheet = $worksheet;
160
        } else {
161
            throw new SheetNotFoundException('The given sheet does not exist in the workbook.');
162
        }
163 4
    }
164
165
    /**
166
     * @param Worksheet $worksheet
167
     * @return void
168
     */
169 89
    private function setCurrentWorksheet($worksheet)
170
    {
171 89
        $this->currentWorksheet = $worksheet;
172 89
    }
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 4
    private function getWorksheetFromExternalSheet($sheet)
181
    {
182 4
        $worksheetFound = null;
183
184 4
        foreach ($this->getWorksheets() as $worksheet) {
185 4
            if ($worksheet->getExternalSheet() === $sheet) {
186 4
                $worksheetFound = $worksheet;
187 4
                break;
188
            }
189
        }
190
191 4
        return $worksheetFound;
192
    }
193
194
    /**
195
     * Adds data 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 array $dataRow Array containing data to be written. Cannot be empty.
200
     *          Example $dataRow = ['data1', 1234, null, '', 'data5'];
201
     * @param Style $style Style to be applied to the row.
202
     * @return void
203
     * @throws IOException If trying to create a new sheet and unable to open the sheet for writing
204
     * @throws WriterException If unable to write data
205
     */
206 64
    public function addRowToCurrentWorksheet($dataRow, Style $style)
207
    {
208 64
        $currentWorksheet = $this->getCurrentWorksheet();
209 64
        $hasReachedMaxRows = $this->hasCurrentWorkseetReachedMaxRows();
210
211
        // if we reached the maximum number of rows for the current sheet...
212 64
        if ($hasReachedMaxRows) {
213
            // ... continue writing in a new sheet if option set
214 4
            if ($this->optionManager->getOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY)) {
215 2
                $currentWorksheet = $this->addNewSheetAndMakeItCurrent();
216
217 2
                $this->addRowWithStyleToWorksheet($currentWorksheet, $dataRow, $style);
218 2
            } else {
219
                // otherwise, do nothing as the data won't be written anyways
220
            }
221
        } else {
222 64
            $this->addRowWithStyleToWorksheet($currentWorksheet, $dataRow, $style);
223
        }
224 61
    }
225
226
    /**
227
     * @return bool Whether the current worksheet has reached the maximum number of rows per sheet.
228
     */
229 64
    private function hasCurrentWorkseetReachedMaxRows()
230
    {
231 64
        $currentWorksheet = $this->getCurrentWorksheet();
232 64
        return ($currentWorksheet->getLastWrittenRowIndex() >= $this->getMaxRowsPerWorksheet());
233
    }
234
235
    /**
236
     * Adds data with the given style to the given sheet.
237
     *
238
     * @param Worksheet $worksheet Worksheet to write the row to
239
     * @param array $dataRow Array containing data to be written. Cannot be empty.
240
     *          Example $dataRow = ['data1', 1234, null, '', 'data5'];
241
     * @param Style $style Style to be applied to the row.
242
     * @return void
243
     * @throws WriterException If unable to write data
244
     */
245 64
    private function addRowWithStyleToWorksheet(Worksheet $worksheet, $dataRow, Style $style)
246
    {
247 64
        $updatedStyle = $this->styleHelper->applyExtraStylesIfNeeded($style, $dataRow);
248 64
        $registeredStyle = $this->styleHelper->registerStyle($updatedStyle);
249 64
        $this->worksheetManager->addRow($worksheet, $dataRow, $registeredStyle);
250
251
        // update max num columns for the worksheet
252 61
        $currentMaxNumColumns = $worksheet->getMaxNumColumns();
253 61
        $cellsCount = count($dataRow);
254 61
        $worksheet->setMaxNumColumns(max($currentMaxNumColumns, $cellsCount));
255 61
    }
256
257
    /**
258
     * Closes the workbook and all its associated sheets.
259
     * All the necessary files are written to disk and zipped together to create the final file.
260
     * All the temporary files are then deleted.
261
     *
262
     * @param resource $finalFilePointer Pointer to the spreadsheet that will be created
263
     * @return void
264
     */
265 70
    public function close($finalFilePointer)
266
    {
267 70
        $this->closeAllWorksheets();
268 70
        $this->closeRemainingObjects();
269 70
        $this->writeAllFilesToDiskAndZipThem($finalFilePointer);
270 70
        $this->cleanupTempFolder();
271 70
    }
272
273
    /**
274
     * Closes custom objects that are still opened
275
     *
276
     * @return void
277
     */
278 34
    protected function closeRemainingObjects()
279
    {
280
        // do nothing by default
281 34
    }
282
283
    /**
284
     * Writes all the necessary files to disk and zip them together to create the final file.
285
     *
286
     * @param resource $finalFilePointer Pointer to the spreadsheet that will be created
287
     * @return void
288
     */
289
    abstract protected function writeAllFilesToDiskAndZipThem($finalFilePointer);
290
291
    /**
292
     * Closes all workbook's associated sheets.
293
     *
294
     * @return void
295
     */
296 70
    private function closeAllWorksheets()
297
    {
298 70
        $worksheets = $this->getWorksheets();
299
300 70
        foreach ($worksheets as $worksheet) {
301 70
            $this->worksheetManager->close($worksheet);
302
        }
303 70
    }
304
305
    /**
306
     * Deletes the root folder created in the temp folder and all its contents.
307
     *
308
     * @return void
309
     */
310 70
    protected function cleanupTempFolder()
311
    {
312 70
        $rootFolder = $this->fileSystemHelper->getRootFolder();
313 70
        $this->fileSystemHelper->deleteFolderRecursively($rootFolder);
314
    }
315
}