Completed
Branch development (b1b115)
by Johannes
10:28
created

Factory::decorate_frame()   F

Complexity

Conditions 37
Paths 5765

Size

Total Lines 202

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 202
rs 0
cc 37
nc 5765
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @package dompdf
4
 * @link    http://dompdf.github.com/
5
 * @author  Benj Carson <[email protected]>
6
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
7
 */
8
namespace Dompdf\Frame;
9
10
use Dompdf\Css\Style;
11
use Dompdf\Dompdf;
12
use Dompdf\Exception;
13
use Dompdf\Frame;
14
use Dompdf\FrameDecorator\AbstractFrameDecorator;
15
use DOMXPath;
16
use Dompdf\FrameDecorator\Page as PageFrameDecorator;
17
use Dompdf\FrameReflower\Page as PageFrameReflower;
18
use Dompdf\Positioner\AbstractPositioner;
19
20
/**
21
 * Contains frame decorating logic
22
 *
23
 * This class is responsible for assigning the correct {@link AbstractFrameDecorator},
24
 * {@link AbstractPositioner}, and {@link AbstractFrameReflower} objects to {@link Frame}
25
 * objects.  This is determined primarily by the Frame's display type, but
26
 * also by the Frame's node's type (e.g. DomElement vs. #text)
27
 *
28
 * @access  private
29
 * @package dompdf
30
 */
31
class Factory
32
{
33
34
     /**
35
     * Array of positioners for specific frame types
36
     *
37
     * @var AbstractPositioner[]
38
     */
39
    protected static $_positioners;
40
41
    /**
42
     * Decorate the root Frame
43
     *
44
     * @param $root   Frame The frame to decorate
45
     * @param $dompdf Dompdf The dompdf instance
46
     *
47
     * @return PageFrameDecorator
48
     */
49
    static function decorate_root(Frame $root, Dompdf $dompdf)
50
    {
51
        $frame = new PageFrameDecorator($root, $dompdf);
52
        $frame->set_reflower(new PageFrameReflower($frame));
53
        $root->set_decorator($frame);
54
55
        return $frame;
56
    }
57
58
    /**
59
     * Decorate a Frame
60
     *
61
     * @param Frame $frame   The frame to decorate
62
     * @param Dompdf $dompdf The dompdf instance
63
     * @param Frame $root    The frame to decorate
64
     *
65
     * @throws Exception
66
     * @return AbstractFrameDecorator
67
     * FIXME: this is admittedly a little smelly...
68
     */
69
    static function decorate_frame(Frame $frame, Dompdf $dompdf, Frame $root = null)
70
    {
71
        if (is_null($dompdf)) {
72
            throw new Exception("The DOMPDF argument is required");
73
        }
74
75
        $style = $frame->get_style();
76
77
        // Floating (and more generally out-of-flow) elements are blocks
78
        // http://coding.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/
79
        if (!$frame->is_in_flow() && in_array($style->display, Style::$INLINE_TYPES)) {
80
            $style->display = "block";
81
        }
82
83
        $display = $style->display;
84
85
        switch ($display) {
86
87
            case "flex": //FIXME: display type not yet supported 
88
            case "table-caption": //FIXME: display type not yet supported
89
            case "block":
90
                $positioner = "Block";
91
                $decorator = "Block";
92
                $reflower = "Block";
93
                break;
94
95
            case "inline-flex": //FIXME: display type not yet supported 
96
            case "inline-block":
97
                $positioner = "Inline";
98
                $decorator = "Block";
99
                $reflower = "Block";
100
                break;
101
102
            case "inline":
103
                $positioner = "Inline";
104
                if ($frame->is_text_node()) {
105
                    $decorator = "Text";
106
                    $reflower = "Text";
107
                } else {
108
                    if ($style->float !== "none") {
109
                        $decorator = "Block";
110
                        $reflower = "Block";
111
                    } else {
112
                        $decorator = "Inline";
113
                        $reflower = "Inline";
114
                    }
115
                }
116
                break;
117
118
            case "table":
119
                $positioner = "Block";
120
                $decorator = "Table";
121
                $reflower = "Table";
122
                break;
123
124
            case "inline-table":
125
                $positioner = "Inline";
126
                $decorator = "Table";
127
                $reflower = "Table";
128
                break;
129
130
            case "table-row-group":
131
            case "table-header-group":
132
            case "table-footer-group":
133
                $positioner = "NullPositioner";
134
                $decorator = "TableRowGroup";
135
                $reflower = "TableRowGroup";
136
                break;
137
138
            case "table-row":
139
                $positioner = "NullPositioner";
140
                $decorator = "TableRow";
141
                $reflower = "TableRow";
142
                break;
143
144
            case "table-cell":
145
                $positioner = "TableCell";
146
                $decorator = "TableCell";
147
                $reflower = "TableCell";
148
                break;
149
150
            case "list-item":
151
                $positioner = "Block";
152
                $decorator = "Block";
153
                $reflower = "Block";
154
                break;
155
156
            case "-dompdf-list-bullet":
157
                if ($style->list_style_position === "inside") {
158
                    $positioner = "Inline";
159
                } else {
160
                    $positioner = "ListBullet";
161
                }
162
163
                if ($style->list_style_image !== "none") {
164
                    $decorator = "ListBulletImage";
165
                } else {
166
                    $decorator = "ListBullet";
167
                }
168
169
                $reflower = "ListBullet";
170
                break;
171
172
            case "-dompdf-image":
173
                $positioner = "Inline";
174
                $decorator = "Image";
175
                $reflower = "Image";
176
                break;
177
178
            case "-dompdf-br":
179
                $positioner = "Inline";
180
                $decorator = "Inline";
181
                $reflower = "Inline";
182
                break;
183
184
            default:
185
                // FIXME: should throw some sort of warning or something?
186
            case "none":
187
                if ($style->_dompdf_keep !== "yes") {
188
                    // Remove the node and the frame
189
                    $frame->get_parent()->remove_child($frame);
190
                    return;
191
                }
192
193
                $positioner = "NullPositioner";
194
                $decorator = "NullFrameDecorator";
195
                $reflower = "NullFrameReflower";
196
                break;
197
        }
198
199
        // Handle CSS position
200
        $position = $style->position;
201
202
        if ($position === "absolute") {
203
            $positioner = "Absolute";
204
        } else {
205
            if ($position === "fixed") {
206
                $positioner = "Fixed";
207
            }
208
        }
209
210
        $node = $frame->get_node();
211
212
        // Handle nodeName
213
        if ($node->nodeName === "img") {
214
            $style->display = "-dompdf-image";
215
            $decorator = "Image";
216
            $reflower = "Image";
217
        }
218
219
        $decorator  = "Dompdf\\FrameDecorator\\$decorator";
220
        $reflower   = "Dompdf\\FrameReflower\\$reflower";
221
222
        /** @var AbstractFrameDecorator $deco */
223
        $deco = new $decorator($frame, $dompdf);
224
225
        $deco->set_positioner(self::getPositionerInstance($positioner));
226
        $deco->set_reflower(new $reflower($deco, $dompdf->getFontMetrics()));
227
228
        if ($root) {
229
            $deco->set_root($root);
230
        }
231
232
        if ($display === "list-item") {
233
            // Insert a list-bullet frame
234
            $xml = $dompdf->getDom();
235
            $bullet_node = $xml->createElement("bullet"); // arbitrary choice
236
            $b_f = new Frame($bullet_node);
237
238
            $node = $frame->get_node();
239
            $parent_node = $node->parentNode;
240
241
            if ($parent_node) {
242
                if (!$parent_node->hasAttribute("dompdf-children-count")) {
243
                    $xpath = new DOMXPath($xml);
244
                    $count = $xpath->query("li", $parent_node)->length;
245
                    $parent_node->setAttribute("dompdf-children-count", $count);
246
                }
247
248
                if (is_numeric($node->getAttribute("value"))) {
249
                    $index = intval($node->getAttribute("value"));
250
                } else {
251
                    if (!$parent_node->hasAttribute("dompdf-counter")) {
252
                        $index = ($parent_node->hasAttribute("start") ? $parent_node->getAttribute("start") : 1);
253
                    } else {
254
                        $index = (int)$parent_node->getAttribute("dompdf-counter") + 1;
255
                    }
256
                }
257
258
                $parent_node->setAttribute("dompdf-counter", $index);
259
                $bullet_node->setAttribute("dompdf-counter", $index);
260
            }
261
262
            $new_style = $dompdf->getCss()->create_style();
263
            $new_style->display = "-dompdf-list-bullet";
264
            $new_style->inherit($style);
265
            $b_f->set_style($new_style);
266
267
            $deco->prepend_child(Factory::decorate_frame($b_f, $dompdf, $root));
268
        }
269
270
        return $deco;
271
    }
272
273
    /**
274
     * Creates Positioners
275
     *
276
     * @param string $type type of positioner to use
277
     * @return AbstractPositioner
278
     */
279
    protected static function getPositionerInstance($type)
280
    {
281
        if (!isset(self::$_positioners[$type])) {
282
            $class = '\\Dompdf\\Positioner\\'.$type;
283
            self::$_positioners[$type] = new $class();
284
        }
285
        return self::$_positioners[$type];
286
    }
287
}
288