This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace nstdio\svg; |
||
3 | |||
4 | use Doctrine\Instantiator\Instantiator; |
||
5 | use nstdio\svg\attributes\Transformable; |
||
6 | use nstdio\svg\container\ContainerInterface; |
||
7 | use nstdio\svg\container\Defs; |
||
8 | use nstdio\svg\container\SVG; |
||
9 | use nstdio\svg\traits\ChildTrait; |
||
10 | use nstdio\svg\traits\ElementTrait; |
||
11 | use nstdio\svg\util\Identifier; |
||
12 | use nstdio\svg\util\Inflector; |
||
13 | use nstdio\svg\util\KeyValueWriter; |
||
14 | use nstdio\svg\util\Transform; |
||
15 | use nstdio\svg\util\TransformInterface; |
||
16 | |||
17 | /** |
||
18 | * Class SVGElement |
||
19 | * The base class for all elements. |
||
20 | * |
||
21 | * @property string $id |
||
22 | * @property string $fill The fill color. |
||
23 | * @property float $height The height attribute of element. |
||
24 | * @property float $width The width attribute of element. |
||
25 | * |
||
26 | * @package nstdio\svg |
||
27 | * @author Edgar Asatryan <[email protected]> |
||
28 | */ |
||
29 | abstract class SVGElement implements ContainerInterface, ElementFactoryInterface |
||
30 | { |
||
31 | use ElementTrait, ChildTrait; |
||
32 | |||
33 | /** |
||
34 | * This attribute will not be converted. |
||
35 | * |
||
36 | * @see SVGElement::__get; |
||
37 | * @var array |
||
38 | */ |
||
39 | private static $notConvertable = ['patternContentUnits', 'patternTransform', 'patternUnits', 'diffuseConstant', 'pointsAtX', 'pointsAtY', 'pointsAtZ', 'limitingConeAngle', 'tableValues', 'filterUnits', 'gradientUnits', 'viewBox', 'repeatCount', 'attributeName', 'attributeType', 'stdDeviation']; |
||
40 | |||
41 | /** |
||
42 | * The parent of `$element`. |
||
43 | * |
||
44 | * @var XMLDocumentInterface | ElementFactoryInterface | ContainerInterface |
||
45 | */ |
||
46 | protected $root; |
||
47 | |||
48 | /** |
||
49 | * The element itself. |
||
50 | * |
||
51 | * @var XMLDocumentInterface | ElementFactoryInterface | ContainerInterface |
||
52 | */ |
||
53 | protected $element; |
||
54 | |||
55 | 150 | public function __construct(ElementInterface $parent) |
|
56 | { |
||
57 | 150 | $this->child = new ElementStorage(); |
|
58 | 150 | $this->root = $parent; |
|
0 ignored issues
–
show
|
|||
59 | 150 | $this->element = $this->createElement($this->getName()); |
|
60 | 150 | $this->root->append($this); |
|
61 | 150 | } |
|
62 | |||
63 | /** |
||
64 | * @inheritdoc |
||
65 | */ |
||
66 | 150 | public function createElement($name, $value = null, $attributes = []) |
|
67 | { |
||
68 | 150 | return $this->root->createElement($name, $value, $attributes); |
|
0 ignored issues
–
show
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 ![]() |
|||
69 | } |
||
70 | |||
71 | /** |
||
72 | * @inheritdoc |
||
73 | */ |
||
74 | abstract public function getName(); |
||
75 | |||
76 | /** |
||
77 | * @inheritdoc |
||
78 | */ |
||
79 | 27 | final public function getRoot() |
|
80 | { |
||
81 | 27 | return $this->root; |
|
82 | } |
||
83 | |||
84 | /** |
||
85 | * @inheritdoc |
||
86 | */ |
||
87 | 150 | final public function getElement() |
|
88 | { |
||
89 | 150 | return $this->element; |
|
90 | } |
||
91 | |||
92 | /** |
||
93 | * @param string[] $except |
||
94 | * |
||
95 | * @see XMLDocumentInterface::attributes() |
||
96 | * @return array |
||
97 | */ |
||
98 | 9 | public function allAttributes(array $except = []) |
|
99 | { |
||
100 | 9 | return $this->element->attributes($except); |
|
101 | } |
||
102 | |||
103 | /** |
||
104 | * In order to have short access to the attributes of an element. Any attribute can be obtained as a public |
||
105 | * property object. Attributes that are written with a hyphen can be obtained through a simple conversion. |
||
106 | * |
||
107 | * ```php |
||
108 | * // ... |
||
109 | * |
||
110 | * echo $circle->strokeWidth; // Property strokeWidth will be transformed into stroke-width and so on. |
||
111 | * echo $blur->stdDeviation; // Property stdDeviation will not converted into std-deviation. |
||
112 | * ``` |
||
113 | * |
||
114 | * For properties `$fill` and `$filter` will be returned something like this `url(#idTheRefToElement)`. In order to |
||
115 | * have direct access to `idTheRefToElement` part, |
||
116 | * ```php |
||
117 | * // ... |
||
118 | * $circle->filter = "url(#someFilterId)"; |
||
119 | * $id = $circle->filterUrl; |
||
120 | * echo $id; // will print someFilterId and same story with fillUrl |
||
121 | * ``` |
||
122 | * You can also have access to attributes with `xlink` namespace as mentioned above. |
||
123 | * For example you need to get `xlink:href` value. If given element doest not have `href` attribute (with no |
||
124 | * namespace prefix) it will try to get `xlink:href`. |
||
125 | * ```php |
||
126 | * $id = $mPath->href; |
||
127 | * echo $id; // will print #someHref. |
||
128 | * ``` |
||
129 | * |
||
130 | * @param string $name The name of property. |
||
131 | * |
||
132 | * @see SVGElement::$notConvertable |
||
133 | * @return null|string |
||
134 | */ |
||
135 | 109 | public function __get($name) |
|
136 | { |
||
137 | 109 | if ($name === 'filterUrl' || $name === 'fillUrl') { |
|
138 | 1 | return $this->getIdFromUrl($name); |
|
139 | } |
||
140 | |||
141 | 109 | $name = $this->convertAttributeName($name); |
|
142 | 109 | $value = $this->element->getAttribute($name); |
|
143 | 109 | if ($value === '') { |
|
144 | 81 | $value = $this->getXLinkAttribute($name); |
|
145 | 81 | } |
|
146 | |||
147 | 109 | return $value === '' ? null : $value; |
|
148 | } |
||
149 | |||
150 | /** |
||
151 | * Has same propose as `__get()` and same `$filterUrl`, `$fillUrl`, name converting policy. |
||
152 | * You can generate an id for the element by assigning null. |
||
153 | * ```php |
||
154 | * // ... |
||
155 | * $circle->id = null; |
||
156 | * echo $circle->id; // will print something like this __circle12345. |
||
157 | * ``` |
||
158 | * |
||
159 | * @param string $name The name of property. |
||
160 | * @param mixed $value The value of property. |
||
161 | */ |
||
162 | 117 | public function __set($name, $value) |
|
163 | { |
||
164 | 117 | if ($name === 'id' && $value === null) { |
|
165 | 37 | $this->element->setAttribute($name, Identifier::random('__' . $this->getName(), 5)); |
|
166 | |||
167 | 37 | return; |
|
168 | } |
||
169 | |||
170 | 107 | if ($value === null || $value === false || $value === '') { |
|
171 | 8 | return; |
|
172 | } |
||
173 | |||
174 | 107 | if ($name === 'filterUrl' || $name === 'fillUrl') { |
|
175 | 23 | $this->handleUrlPostfixAttribute($name, $value); |
|
176 | 23 | } |
|
177 | |||
178 | 107 | $name = $this->convertAttributeName($name); |
|
179 | 107 | $this->element->setAttribute($name, $value); |
|
180 | 107 | } |
|
181 | |||
182 | /** |
||
183 | * @param string $name The local name of `xlink` namespaced attribute. |
||
184 | * |
||
185 | * @return string The value of attribute. |
||
186 | */ |
||
187 | 81 | public function getXLinkAttribute($name) |
|
188 | { |
||
189 | 81 | return $this->element->getAttributeNS('xlink', $name); |
|
190 | } |
||
191 | |||
192 | /** |
||
193 | * @param string $name The local name of `xlink` attribute. |
||
194 | * @param mixed $value The value of attribute. |
||
195 | */ |
||
196 | 1 | public function setXLinkAttribute($name, $value) |
|
197 | { |
||
198 | 1 | $this->element->setAttributeNS('xlink', "xlink:$name", $value); |
|
199 | 1 | } |
|
200 | |||
201 | /** |
||
202 | * If attribute name is convertable converts it from camelCase to dashed. |
||
203 | * |
||
204 | * @param string $name The string to convert. |
||
205 | * |
||
206 | * @return string The converted string. |
||
207 | */ |
||
208 | 120 | private function convertAttributeName($name) |
|
209 | { |
||
210 | 120 | return !in_array($name, self::$notConvertable) ? Inflector::camel2dash($name) : $name; |
|
211 | } |
||
212 | |||
213 | /** |
||
214 | * @inheritdoc |
||
215 | */ |
||
216 | 50 | public function apply(array $assoc) |
|
217 | { |
||
218 | 50 | $filtered = []; |
|
219 | 50 | foreach ($assoc as $attribute => $value) { |
|
220 | 49 | $filtered[$this->convertAttributeName($attribute)] = $value; |
|
221 | 50 | } |
|
222 | 50 | KeyValueWriter::apply($this->element, $filtered); |
|
223 | |||
224 | 50 | return $this; |
|
225 | } |
||
226 | |||
227 | /** |
||
228 | * It removes the object itself from the DOM and from the list of the children of its parent. |
||
229 | */ |
||
230 | 3 | protected function selfRemove() |
|
231 | { |
||
232 | 3 | $this->getRoot()->removeChild($this); |
|
0 ignored issues
–
show
The method
removeChild() does not seem to exist on object<nstdio\svg\XMLDocumentInterface> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
233 | 3 | } |
|
234 | |||
235 | /** |
||
236 | * @return SVG The root element of hierarchy. |
||
237 | */ |
||
238 | 3 | protected function getSVG() |
|
239 | { |
||
240 | 3 | if ($this->root instanceof SVG) { |
|
241 | 3 | return $this->root; |
|
242 | } |
||
243 | $element = $this->root; |
||
244 | |||
245 | do { |
||
246 | $element = $element->getRoot(); |
||
247 | } while (!($element instanceof SVG)); |
||
248 | |||
249 | return $element; |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Returns standard `defs` element for `svg`. |
||
254 | * |
||
255 | * @param ElementInterface $container Where to search `defs` element. |
||
256 | * |
||
257 | * @return Defs The `defs` element. |
||
258 | */ |
||
259 | 61 | protected static function getDefs(ElementInterface $container) |
|
260 | { |
||
261 | 61 | if ($container instanceof Defs) { |
|
262 | 11 | return $container; |
|
263 | } |
||
264 | |||
265 | 50 | if ($container instanceof SVG) { |
|
266 | 50 | $defs = $container->getFirstChild(); |
|
267 | 50 | } else { |
|
268 | /** @var SVGElement $container */ |
||
269 | $defs = $container->getSVG()->getFirstChild(); |
||
270 | } |
||
271 | |||
272 | 50 | return $defs; |
|
273 | } |
||
274 | |||
275 | /** |
||
276 | * @inheritdoc |
||
277 | */ |
||
278 | 2 | public function copy(array $apply = [], array $ignore = [], ContainerInterface $parent = null) |
|
279 | { |
||
280 | /** @var SVGElement $instance */ |
||
281 | 2 | $instance = (new Instantiator())->instantiate(get_class($this)); |
|
282 | 2 | $instance->root = $parent === null ? $this->getRoot() : $parent; |
|
0 ignored issues
–
show
It seems like
$parent === null ? $this->getRoot() : $parent can also be of type object<nstdio\svg\container\ContainerInterface> . However, the property $root is declared as type object<nstdio\svg\XMLDocumentInterface> . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||
283 | 2 | $instance->child = new ElementStorage(); |
|
284 | 2 | $instance->element = $this->createElement($this->getName()); |
|
285 | 2 | $instance->id = null; |
|
286 | |||
287 | 2 | if ($instance instanceof TransformInterface && $this instanceof Transformable) { |
|
0 ignored issues
–
show
The class
nstdio\svg\util\TransformInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
288 | $instance->transformImpl = Transform::newInstance($this->getTransformAttribute()); |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
nstdio\svg\SVGElement as the method getTransformAttribute() does only exist in the following sub-classes of nstdio\svg\SVGElement : nstdio\svg\container\G , nstdio\svg\container\Pattern , nstdio\svg\shape\Circle , nstdio\svg\shape\Ellipse , nstdio\svg\shape\Line , nstdio\svg\shape\Path , nstdio\svg\shape\Polygon , nstdio\svg\shape\Polyline , nstdio\svg\shape\Rect , nstdio\svg\shape\RoundedShape , nstdio\svg\shape\Shape . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
289 | } |
||
290 | 2 | $ignore[] = 'id'; |
|
291 | 2 | $apply = array_merge($this->allAttributes($ignore), $apply); |
|
292 | 2 | $instance->apply($apply); |
|
293 | 2 | $parent === null ? $this->root->append($instance) : $parent->append($instance); |
|
0 ignored issues
–
show
The method
append() does not exist on nstdio\svg\XMLDocumentInterface . Did you maybe mean appendChild() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
294 | |||
295 | 2 | return $instance; |
|
296 | } |
||
297 | |||
298 | /** |
||
299 | * Places the `$value` into `url(#$value)` if `url(#` is not present. |
||
300 | * |
||
301 | * @param string $attribute The `$filterUrl` or `$fillUrl` properties. |
||
302 | * @param string $value The wrapped string. |
||
303 | */ |
||
304 | 23 | private function handleUrlPostfixAttribute(&$attribute, &$value) |
|
305 | { |
||
306 | 23 | $attribute = substr($attribute, 0, strrpos($attribute, 'U')); |
|
307 | 23 | if (strpos($value, "url(#") !== 0) { |
|
308 | 23 | $value = "url(#" . $value . ")"; |
|
309 | 23 | } |
|
310 | 23 | } |
|
311 | |||
312 | /** |
||
313 | * Retrieves the id from the `url(#id)` string. |
||
314 | * |
||
315 | * @param string $attribute The `$filterUrl` or `$fillUrl` properties. |
||
316 | * |
||
317 | * @return string The extracted string. |
||
318 | */ |
||
319 | 1 | private function getIdFromUrl($attribute) |
|
320 | { |
||
321 | 1 | $attribute = substr($attribute, 0, strrpos($attribute, 'U')); |
|
322 | 1 | return str_replace(['url(#', ')'], '', $this->element->getAttribute($attribute)); |
|
323 | } |
||
324 | } |
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..