Completed
Push — master ( 60e18b...ffd1f4 )
by Edgar
39:02
created

SVGElement::createDefs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace nstdio\svg;
3
4
use nstdio\svg\container\ContainerInterface;
5
use nstdio\svg\container\SVG;
6
use nstdio\svg\traits\ChildTrait;
7
use nstdio\svg\traits\ElementTrait;
8
use nstdio\svg\util\Identifier;
9
use nstdio\svg\util\Inflector;
10
use nstdio\svg\util\KeyValueWriter;
11
12
/**
13
 * Class SVGElement
14
 *
15
 * @property string $id
16
 * @property string $fill The fill color.
17
 *
18
 * @package nstdio\svg
19
 * @author  Edgar Asatryan <[email protected]>
20
 */
21
abstract class SVGElement implements ContainerInterface, ElementFactoryInterface
22
{
23
    use ElementTrait, ChildTrait;
24
25
    private static $notConvertable = ['diffuseConstant', 'pointsAtX', 'pointsAtY', 'pointsAtZ', 'limitingConeAngle', 'tableValues', 'filterUnits', 'gradientUnits', 'viewBox', 'repeatCount', 'attributeName', 'attributeType', 'stdDeviation'];
26
27
    /**
28
     * @var XMLDocumentInterface | ElementInterface | ElementFactoryInterface | ContainerInterface
29
     */
30
    protected $root;
31
32
    /**
33
     * @var XMLDocumentInterface | ElementInterface | ElementFactoryInterface | ContainerInterface
34
     */
35
    protected $element;
36
37
    public function __construct(ElementInterface $parent)
38
    {
39
        $this->child = new ElementStorage();
40
        $this->root = $parent;
0 ignored issues
show
Documentation Bug introduced by
It seems like $parent of type object<nstdio\svg\ElementInterface> is incompatible with the declared type object<nstdio\svg\XMLDocumentInterface> of property $root.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
41
        $this->element = $this->createElement($this->getName());
42
        $this->root->append($this);
43
    }
44
45
    public function createElement($name, $value = null, $attributes = [])
46
    {
47
        return $this->root->createElement($name, $value, $attributes);
0 ignored issues
show
Unused Code introduced by
The call to XMLDocumentInterface::createElement() has too many arguments starting with $attributes.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
48
    }
49
50
    abstract public function getName();
51
52
    final public function getRoot()
53
    {
54
        return $this->root;
55
    }
56
57
    final public function getElement()
58
    {
59
        return $this->element;
60
    }
61
62
    public function allAttributes(array $except = [])
63
    {
64
        return $this->element->attributes($except);
65
    }
66
67
    public function __get($name)
68
    {
69
        $name = Inflector::camel2dash($name);
70
        $value = $this->element->getAttribute($name);
71
        if ($value === '') {
72
            $value = $this->getXLinkAttribute($name);
73
        }
74
75
        return $value === '' ? null : $value;
76
    }
77
78
    public function __set($name, $value)
79
    {
80
        if ($name === 'id' && $value === null) {
81
            $this->element->setAttribute($name, Identifier::random('__' . $this->getName(), 5));
82
83
            return;
84
        }
85
86
        if ($value === null || $value === false || $value === '') {
87
            return;
88
        }
89
        $name = $this->convertAttributeName($name);
90
        $this->element->setAttribute($name, $value);
91
    }
92
93
    public function getXLinkAttribute($name)
94
    {
95
        return $this->element->getAttributeNS('xlink', $name);
96
    }
97
98
    /**
99
     * @param $name
100
     *
101
     * @return string
102
     */
103
    private function convertAttributeName($name)
104
    {
105
        return !in_array($name, self::$notConvertable) ? Inflector::camel2dash($name) : $name;
106
    }
107
108
    /**
109
     * @inheritdoc
110
     */
111
    public function apply(array $assoc)
112
    {
113
        $filtered = [];
114
        foreach ($assoc as $attribute => $value) {
115
            $filtered[$this->convertAttributeName($attribute)] = $value;
116
        }
117
        KeyValueWriter::apply($this->element, $filtered);
118
119
        return $this;
120
    }
121
122
    protected function setAttribute($name, $value, $xLink = false)
123
    {
124
        if ($xLink === true) {
125
            $this->element->setAttributeNS('xlink', $name, $value);
126
        } else {
127
            $this->element->setAttribute($name, $value);
128
        }
129
    }
130
131
    public function getSVG()
132
    {
133
        if ($this->root instanceof SVG) {
134
            return $this->root;
135
        }
136
        $element = $this->root;
137
138
        do {
139
            $element = $element->getRoot();
140
        } while (!($element instanceof SVG));
141
142
        return $element;
143
    }
144
}