Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.43% covered (success)
98.43%
125 / 127
87.50% covered (warning)
87.50%
7 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
ListItem
98.43% covered (success)
98.43%
125 / 127
87.50% covered (warning)
87.50%
7 / 8
14
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getListType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setListType
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 getNumStyle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setNumStyle
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 getNumId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setNumId
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getListTypeStyle
100.00% covered (success)
100.00%
105 / 105
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2/**
3 * This file is part of PHPWord - A pure PHP library for reading and writing
4 * word processing documents.
5 *
6 * PHPWord is free software distributed under the terms of the GNU Lesser
7 * General Public License version 3 as published by the Free Software Foundation.
8 *
9 * For the full copyright and license information, please read the LICENSE
10 * file that was distributed with this source code. For the full list of
11 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
12 *
13 * @see         https://github.com/PHPOffice/PHPWord
14 *
15 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16 */
17
18namespace PhpOffice\PhpWord\Style;
19
20use PhpOffice\PhpWord\Style;
21
22/**
23 * List item style.
24 *
25 * Before version 0.10.0, numbering style is defined statically with $listType.
26 * After version 0.10.0, numbering style is defined by using Numbering and
27 * recorded by $numStyle. $listStyle is maintained for backward compatility
28 */
29class ListItem extends AbstractStyle
30{
31    const TYPE_SQUARE_FILLED = 1;
32    const TYPE_BULLET_FILLED = 3; // default
33    const TYPE_BULLET_EMPTY = 5;
34    const TYPE_NUMBER = 7;
35    const TYPE_NUMBER_NESTED = 8;
36    const TYPE_ALPHANUM = 9;
37
38    /**
39     * Legacy list type.
40     *
41     * @var int
42     */
43    private $listType;
44
45    /**
46     * Numbering style name.
47     *
48     * @var string
49     *
50     * @since 0.10.0
51     */
52    private $numStyle;
53
54    /**
55     * Numbering definition instance ID.
56     *
57     * @var int
58     *
59     * @since 0.10.0
60     */
61    private $numId;
62
63    /**
64     * Create new instance.
65     *
66     * @param string $numStyle
67     */
68    public function __construct($numStyle = null)
69    {
70        if ($numStyle !== null) {
71            $this->setNumStyle($numStyle);
72        } else {
73            $this->setListType();
74        }
75    }
76
77    /**
78     * Get List Type.
79     *
80     * @return int
81     */
82    public function getListType()
83    {
84        return $this->listType;
85    }
86
87    /**
88     * Set legacy list type for version < 0.10.0.
89     *
90     * @param int $value
91     *
92     * @return self
93     */
94    public function setListType($value = self::TYPE_BULLET_FILLED)
95    {
96        $enum = [
97            self::TYPE_SQUARE_FILLED, self::TYPE_BULLET_FILLED,
98            self::TYPE_BULLET_EMPTY, self::TYPE_NUMBER,
99            self::TYPE_NUMBER_NESTED, self::TYPE_ALPHANUM,
100        ];
101        $this->listType = $this->setEnumVal($value, $enum, $this->listType);
102        $this->getListTypeStyle();
103
104        return $this;
105    }
106
107    /**
108     * Get numbering style name.
109     *
110     * @return string
111     */
112    public function getNumStyle()
113    {
114        return $this->numStyle;
115    }
116
117    /**
118     * Set numbering style name.
119     *
120     * @param string $value
121     *
122     * @return self
123     */
124    public function setNumStyle($value)
125    {
126        $this->numStyle = $value;
127        $numStyleObject = Style::getStyle($this->numStyle);
128        if ($numStyleObject instanceof Numbering) {
129            $this->numId = $numStyleObject->getIndex();
130            $numStyleObject->setNumId($this->numId);
131        }
132
133        return $this;
134    }
135
136    /**
137     * Get numbering Id.
138     *
139     * @return int
140     */
141    public function getNumId()
142    {
143        return $this->numId;
144    }
145
146    /**
147     * Set numbering Id. Same numId means same list.
148     *
149     * @param mixed $numInt
150     */
151    public function setNumId($numInt): void
152    {
153        $this->numId = $numInt;
154        $this->getListTypeStyle();
155    }
156
157    /**
158     * Get legacy numbering definition.
159     *
160     * @return array
161     *
162     * @since 0.10.0
163     */
164    private function getListTypeStyle()
165    {
166        // Check if legacy style already registered in global Style collection
167        $numStyle = 'PHPWordListType' . $this->listType;
168
169        if ($this->numId) {
170            $numStyle .= 'NumId' . $this->numId;
171        }
172
173        if (Style::getStyle($numStyle) !== null) {
174            $this->setNumStyle($numStyle);
175
176            return;
177        }
178
179        // Property mapping for numbering level information
180        $properties = ['start', 'format', 'text', 'alignment', 'tabPos', 'left', 'hanging', 'font', 'hint'];
181
182        // Legacy level information
183        $listTypeStyles = [
184            self::TYPE_SQUARE_FILLED => [
185                'type' => 'hybridMultilevel',
186                'levels' => [
187                    0 => '1, bullet, ï‚§, left, 720, 720, 360, Wingdings, default',
188                    1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
189                    2 => '1, bullet, ï‚§, left, 2160, 2160, 360, Wingdings, default',
190                    3 => '1, bullet, ï‚·, left, 2880, 2880, 360, Symbol, default',
191                    4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
192                    5 => '1, bullet, ï‚§, left, 4320, 4320, 360, Wingdings, default',
193                    6 => '1, bullet, ï‚·, left, 5040, 5040, 360, Symbol, default',
194                    7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
195                    8 => '1, bullet, ï‚§, left, 6480, 6480, 360, Wingdings, default',
196                ],
197            ],
198            self::TYPE_BULLET_FILLED => [
199                'type' => 'hybridMultilevel',
200                'levels' => [
201                    0 => '1, bullet, ï‚·, left, 720, 720, 360, Symbol, default',
202                    1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
203                    2 => '1, bullet, ï‚§, left, 2160, 2160, 360, Wingdings, default',
204                    3 => '1, bullet, ï‚·, left, 2880, 2880, 360, Symbol, default',
205                    4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
206                    5 => '1, bullet, ï‚§, left, 4320, 4320, 360, Wingdings, default',
207                    6 => '1, bullet, ï‚·, left, 5040, 5040, 360, Symbol, default',
208                    7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
209                    8 => '1, bullet, ï‚§, left, 6480, 6480, 360, Wingdings, default',
210                ],
211            ],
212            self::TYPE_BULLET_EMPTY => [
213                'type' => 'hybridMultilevel',
214                'levels' => [
215                    0 => '1, bullet, o, left, 720, 720, 360, Courier New, default',
216                    1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
217                    2 => '1, bullet, ï‚§, left, 2160, 2160, 360, Wingdings, default',
218                    3 => '1, bullet, ï‚·, left, 2880, 2880, 360, Symbol, default',
219                    4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
220                    5 => '1, bullet, ï‚§, left, 4320, 4320, 360, Wingdings, default',
221                    6 => '1, bullet, ï‚·, left, 5040, 5040, 360, Symbol, default',
222                    7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
223                    8 => '1, bullet, ï‚§, left, 6480, 6480, 360, Wingdings, default',
224                ],
225            ],
226            self::TYPE_NUMBER => [
227                'type' => 'hybridMultilevel',
228                'levels' => [
229                    0 => '1, decimal, %1., left, 720, 720, 360, , default',
230                    1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
231                    2 => '1, bullet, ï‚§, left, 2160, 2160, 360, Wingdings, default',
232                    3 => '1, bullet, ï‚·, left, 2880, 2880, 360, Symbol, default',
233                    4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
234                    5 => '1, bullet, ï‚§, left, 4320, 4320, 360, Wingdings, default',
235                    6 => '1, bullet, ï‚·, left, 5040, 5040, 360, Symbol, default',
236                    7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
237                    8 => '1, bullet, ï‚§, left, 6480, 6480, 360, Wingdings, default',
238                ],
239            ],
240            self::TYPE_NUMBER_NESTED => [
241                'type' => 'multilevel',
242                'levels' => [
243                    0 => '1, decimal, %1., left, 360, 360, 360, , ',
244                    1 => '1, decimal, %1.%2., left, 792, 792, 432, , ',
245                    2 => '1, decimal, %1.%2.%3., left, 1224, 1224, 504, , ',
246                    3 => '1, decimal, %1.%2.%3.%4., left, 1800, 1728, 648, , ',
247                    4 => '1, decimal, %1.%2.%3.%4.%5., left, 2520, 2232, 792, , ',
248                    5 => '1, decimal, %1.%2.%3.%4.%5.%6., left, 2880, 2736, 936, , ',
249                    6 => '1, decimal, %1.%2.%3.%4.%5.%6.%7., left, 3600, 3240, 1080, , ',
250                    7 => '1, decimal, %1.%2.%3.%4.%5.%6.%7.%8., left, 3960, 3744, 1224, , ',
251                    8 => '1, decimal, %1.%2.%3.%4.%5.%6.%7.%8.%9., left, 4680, 4320, 1440, , ',
252                ],
253            ],
254            self::TYPE_ALPHANUM => [
255                'type' => 'multilevel',
256                'levels' => [
257                    0 => '1, decimal, %1., left, 720, 720, 360, , ',
258                    1 => '1, lowerLetter, %2., left, 1440, 1440, 360, , ',
259                    2 => '1, lowerRoman, %3., right, 2160, 2160, 180, , ',
260                    3 => '1, decimal, %4., left, 2880, 2880, 360, , ',
261                    4 => '1, lowerLetter, %5., left, 3600, 3600, 360, , ',
262                    5 => '1, lowerRoman, %6., right, 4320, 4320, 180, , ',
263                    6 => '1, decimal, %7., left, 5040, 5040, 360, , ',
264                    7 => '1, lowerLetter, %8., left, 5760, 5760, 360, , ',
265                    8 => '1, lowerRoman, %9., right, 6480, 6480, 180, , ',
266                ],
267            ],
268        ];
269
270        // Populate style and register to global Style register
271        $style = $listTypeStyles[$this->listType];
272        $numProperties = count($properties);
273        foreach ($style['levels'] as $key => $value) {
274            $level = [];
275            $levelProperties = explode(', ', $value);
276            $level['level'] = $key;
277            for ($i = 0; $i < $numProperties; ++$i) {
278                $property = $properties[$i];
279                $level[$property] = $levelProperties[$i];
280            }
281            $style['levels'][$key] = $level;
282        }
283        Style::addNumberingStyle($numStyle, $style);
284        $this->setNumStyle($numStyle);
285    }
286}