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