1<?php
2
3namespace PhpOffice\PhpSpreadsheet\Style;
4
5use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
6
7class Borders extends Supervisor
8{
9    // Diagonal directions
10    const DIAGONAL_NONE = 0;
11    const DIAGONAL_UP = 1;
12    const DIAGONAL_DOWN = 2;
13    const DIAGONAL_BOTH = 3;
14
15    /**
16     * Left.
17     *
18     * @var Border
19     */
20    protected $left;
21
22    /**
23     * Right.
24     *
25     * @var Border
26     */
27    protected $right;
28
29    /**
30     * Top.
31     *
32     * @var Border
33     */
34    protected $top;
35
36    /**
37     * Bottom.
38     *
39     * @var Border
40     */
41    protected $bottom;
42
43    /**
44     * Diagonal.
45     *
46     * @var Border
47     */
48    protected $diagonal;
49
50    /**
51     * DiagonalDirection.
52     *
53     * @var int
54     */
55    protected $diagonalDirection;
56
57    /**
58     * All borders pseudo-border. Only applies to supervisor.
59     *
60     * @var Border
61     */
62    protected $allBorders;
63
64    /**
65     * Outline pseudo-border. Only applies to supervisor.
66     *
67     * @var Border
68     */
69    protected $outline;
70
71    /**
72     * Inside pseudo-border. Only applies to supervisor.
73     *
74     * @var Border
75     */
76    protected $inside;
77
78    /**
79     * Vertical pseudo-border. Only applies to supervisor.
80     *
81     * @var Border
82     */
83    protected $vertical;
84
85    /**
86     * Horizontal pseudo-border. Only applies to supervisor.
87     *
88     * @var Border
89     */
90    protected $horizontal;
91
92    /**
93     * Create a new Borders.
94     *
95     * @param bool $isSupervisor Flag indicating if this is a supervisor or not
96     *                                    Leave this value at default unless you understand exactly what
97     *                                        its ramifications are
98     * @param bool $isConditional Flag indicating if this is a conditional style or not
99     *                                    Leave this value at default unless you understand exactly what
100     *                                        its ramifications are
101     */
102    public function __construct($isSupervisor = false, $isConditional = false)
103    {
104        // Supervisor?
105        parent::__construct($isSupervisor);
106
107        // Initialise values
108        $this->left = new Border($isSupervisor, $isConditional);
109        $this->right = new Border($isSupervisor, $isConditional);
110        $this->top = new Border($isSupervisor, $isConditional);
111        $this->bottom = new Border($isSupervisor, $isConditional);
112        $this->diagonal = new Border($isSupervisor, $isConditional);
113        $this->diagonalDirection = self::DIAGONAL_NONE;
114
115        // Specially for supervisor
116        if ($isSupervisor) {
117            // Initialize pseudo-borders
118            $this->allBorders = new Border(true);
119            $this->outline = new Border(true);
120            $this->inside = new Border(true);
121            $this->vertical = new Border(true);
122            $this->horizontal = new Border(true);
123
124            // bind parent if we are a supervisor
125            $this->left->bindParent($this, 'left');
126            $this->right->bindParent($this, 'right');
127            $this->top->bindParent($this, 'top');
128            $this->bottom->bindParent($this, 'bottom');
129            $this->diagonal->bindParent($this, 'diagonal');
130            $this->allBorders->bindParent($this, 'allBorders');
131            $this->outline->bindParent($this, 'outline');
132            $this->inside->bindParent($this, 'inside');
133            $this->vertical->bindParent($this, 'vertical');
134            $this->horizontal->bindParent($this, 'horizontal');
135        }
136    }
137
138    /**
139     * Get the shared style component for the currently active cell in currently active sheet.
140     * Only used for style supervisor.
141     *
142     * @return Borders
143     */
144    public function getSharedComponent()
145    {
146        return $this->parent->getSharedComponent()->getBorders();
147    }
148
149    /**
150     * Build style array from subcomponents.
151     *
152     * @param array $array
153     *
154     * @return array
155     */
156    public function getStyleArray($array)
157    {
158        return ['borders' => $array];
159    }
160
161    /**
162     * Apply styles from array.
163     *
164     * <code>
165     * $spreadsheet->getActiveSheet()->getStyle('B2')->getBorders()->applyFromArray(
166     *         [
167     *             'bottom' => [
168     *                 'borderStyle' => Border::BORDER_DASHDOT,
169     *                 'color' => [
170     *                     'rgb' => '808080'
171     *                 ]
172     *             ],
173     *             'top' => [
174     *                 'borderStyle' => Border::BORDER_DASHDOT,
175     *                 'color' => [
176     *                     'rgb' => '808080'
177     *                 ]
178     *             ]
179     *         ]
180     * );
181     * </code>
182     *
183     * <code>
184     * $spreadsheet->getActiveSheet()->getStyle('B2')->getBorders()->applyFromArray(
185     *         [
186     *             'allBorders' => [
187     *                 'borderStyle' => Border::BORDER_DASHDOT,
188     *                 'color' => [
189     *                     'rgb' => '808080'
190     *                 ]
191     *             ]
192     *         ]
193     * );
194     * </code>
195     *
196     * @param array $pStyles Array containing style information
197     *
198     * @throws PhpSpreadsheetException
199     *
200     * @return Borders
201     */
202    public function applyFromArray(array $pStyles)
203    {
204        if ($this->isSupervisor) {
205            $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles));
206        } else {
207            if (isset($pStyles['left'])) {
208                $this->getLeft()->applyFromArray($pStyles['left']);
209            }
210            if (isset($pStyles['right'])) {
211                $this->getRight()->applyFromArray($pStyles['right']);
212            }
213            if (isset($pStyles['top'])) {
214                $this->getTop()->applyFromArray($pStyles['top']);
215            }
216            if (isset($pStyles['bottom'])) {
217                $this->getBottom()->applyFromArray($pStyles['bottom']);
218            }
219            if (isset($pStyles['diagonal'])) {
220                $this->getDiagonal()->applyFromArray($pStyles['diagonal']);
221            }
222            if (isset($pStyles['diagonalDirection'])) {
223                $this->setDiagonalDirection($pStyles['diagonalDirection']);
224            }
225            if (isset($pStyles['allBorders'])) {
226                $this->getLeft()->applyFromArray($pStyles['allBorders']);
227                $this->getRight()->applyFromArray($pStyles['allBorders']);
228                $this->getTop()->applyFromArray($pStyles['allBorders']);
229                $this->getBottom()->applyFromArray($pStyles['allBorders']);
230            }
231        }
232
233        return $this;
234    }
235
236    /**
237     * Get Left.
238     *
239     * @return Border
240     */
241    public function getLeft()
242    {
243        return $this->left;
244    }
245
246    /**
247     * Get Right.
248     *
249     * @return Border
250     */
251    public function getRight()
252    {
253        return $this->right;
254    }
255
256    /**
257     * Get Top.
258     *
259     * @return Border
260     */
261    public function getTop()
262    {
263        return $this->top;
264    }
265
266    /**
267     * Get Bottom.
268     *
269     * @return Border
270     */
271    public function getBottom()
272    {
273        return $this->bottom;
274    }
275
276    /**
277     * Get Diagonal.
278     *
279     * @return Border
280     */
281    public function getDiagonal()
282    {
283        return $this->diagonal;
284    }
285
286    /**
287     * Get AllBorders (pseudo-border). Only applies to supervisor.
288     *
289     * @throws PhpSpreadsheetException
290     *
291     * @return Border
292     */
293    public function getAllBorders()
294    {
295        if (!$this->isSupervisor) {
296            throw new PhpSpreadsheetException('Can only get pseudo-border for supervisor.');
297        }
298
299        return $this->allBorders;
300    }
301
302    /**
303     * Get Outline (pseudo-border). Only applies to supervisor.
304     *
305     * @throws PhpSpreadsheetException
306     *
307     * @return Border
308     */
309    public function getOutline()
310    {
311        if (!$this->isSupervisor) {
312            throw new PhpSpreadsheetException('Can only get pseudo-border for supervisor.');
313        }
314
315        return $this->outline;
316    }
317
318    /**
319     * Get Inside (pseudo-border). Only applies to supervisor.
320     *
321     * @throws PhpSpreadsheetException
322     *
323     * @return Border
324     */
325    public function getInside()
326    {
327        if (!$this->isSupervisor) {
328            throw new PhpSpreadsheetException('Can only get pseudo-border for supervisor.');
329        }
330
331        return $this->inside;
332    }
333
334    /**
335     * Get Vertical (pseudo-border). Only applies to supervisor.
336     *
337     * @throws PhpSpreadsheetException
338     *
339     * @return Border
340     */
341    public function getVertical()
342    {
343        if (!$this->isSupervisor) {
344            throw new PhpSpreadsheetException('Can only get pseudo-border for supervisor.');
345        }
346
347        return $this->vertical;
348    }
349
350    /**
351     * Get Horizontal (pseudo-border). Only applies to supervisor.
352     *
353     * @throws PhpSpreadsheetException
354     *
355     * @return Border
356     */
357    public function getHorizontal()
358    {
359        if (!$this->isSupervisor) {
360            throw new PhpSpreadsheetException('Can only get pseudo-border for supervisor.');
361        }
362
363        return $this->horizontal;
364    }
365
366    /**
367     * Get DiagonalDirection.
368     *
369     * @return int
370     */
371    public function getDiagonalDirection()
372    {
373        if ($this->isSupervisor) {
374            return $this->getSharedComponent()->getDiagonalDirection();
375        }
376
377        return $this->diagonalDirection;
378    }
379
380    /**
381     * Set DiagonalDirection.
382     *
383     * @param int $pValue see self::DIAGONAL_*
384     *
385     * @return Borders
386     */
387    public function setDiagonalDirection($pValue)
388    {
389        if ($pValue == '') {
390            $pValue = self::DIAGONAL_NONE;
391        }
392        if ($this->isSupervisor) {
393            $styleArray = $this->getStyleArray(['diagonalDirection' => $pValue]);
394            $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
395        } else {
396            $this->diagonalDirection = $pValue;
397        }
398
399        return $this;
400    }
401
402    /**
403     * Get hash code.
404     *
405     * @return string Hash code
406     */
407    public function getHashCode()
408    {
409        if ($this->isSupervisor) {
410            return $this->getSharedComponent()->getHashcode();
411        }
412
413        return md5(
414            $this->getLeft()->getHashCode() .
415            $this->getRight()->getHashCode() .
416            $this->getTop()->getHashCode() .
417            $this->getBottom()->getHashCode() .
418            $this->getDiagonal()->getHashCode() .
419            $this->getDiagonalDirection() .
420            __CLASS__
421        );
422    }
423}
424