diff --git a/resources/functionMap.php b/resources/functionMap.php index 82789aea05..b8e2afaf1e 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -1572,8 +1572,8 @@ 'DOMElement::get_attribute_node' => ['DomAttribute', 'name'=>'string'], 'DOMElement::get_elements_by_tagname' => ['array', 'name'=>'string'], 'DOMElement::getAttribute' => ['string', 'name'=>'string'], -'DOMElement::getAttributeNode' => ['DOMAttr', 'name'=>'string'], -'DOMElement::getAttributeNodeNS' => ['DOMAttr', 'namespaceuri'=>'string', 'localname'=>'string'], +'DOMElement::getAttributeNode' => ['__benevolent', 'name'=>'string'], +'DOMElement::getAttributeNodeNS' => ['__benevolent', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::getAttributeNS' => ['string', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::getElementsByTagName' => ['DOMNodeList', 'name'=>'string'], 'DOMElement::getElementsByTagNameNS' => ['DOMNodeList', 'namespaceuri'=>'string', 'localname'=>'string'], diff --git a/tests/PHPStan/Analyser/nsrt/DOMLegacyNamedNodeMap.php b/tests/PHPStan/Analyser/nsrt/DOMLegacyNamedNodeMap.php new file mode 100644 index 0000000000..5aec04c51a --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/DOMLegacyNamedNodeMap.php @@ -0,0 +1,49 @@ +hasAttributes()) { + assertType('DOMNamedNodeMap', $node->attributes); + } else { + // Can be either null or an empty DOMNamedNodeMap + assertType('DOMNamedNodeMap|null', $node->attributes); + } + } + + public function element_node(DOMElement $element): void + { + assertType('DOMNamedNodeMap', $element->attributes); + if ($element->hasAttribute('class')) { + $attribute = $element->getAttributeNode('class'); + assertType('(DOMAttr|false)', $attribute); // Could be DOMAttr + assertType('string', $attribute->value); + } else { + $attribute = $element->getAttributeNode('class'); + assertType('(DOMAttr|false)', $attribute); // Could be false + } + } + + public function element_node_attribute_fetch_via_attributes_property(DOMElement $element): void + { + assertType('DOMNamedNodeMap', $element->attributes); + if ($element->hasAttribute('class')) { + $attribute = $element->attributes->getNamedItem('class'); + if ($attribute === null) { + return; + } + assertType(DOMAttr::class, $attribute); + assertType('string', $attribute->value); + } + } +} diff --git a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php index 85885856b0..e5e2edc4d8 100644 --- a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php @@ -1216,6 +1216,14 @@ public function testPrivatePropertyWithAllowedPropertyTagIsPublic(): void $this->analyse([__DIR__ . '/data/private-property-with-allowed-property-tag-is-public.php'], []); } + public function testDomExtensionLegacyTemplateNodes(): void + { + $this->checkThisOnly = false; + $this->checkUnionTypes = true; + $this->checkDynamicProperties = true; + $this->analyse([__DIR__ . '/data/dom-legacy-ext-template-nodes.php'], []); + } + public function testBug13537(): void { $this->checkThisOnly = false; diff --git a/tests/PHPStan/Rules/Properties/data/dom-legacy-ext-template-nodes.php b/tests/PHPStan/Rules/Properties/data/dom-legacy-ext-template-nodes.php new file mode 100644 index 0000000000..262510c714 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/dom-legacy-ext-template-nodes.php @@ -0,0 +1,33 @@ +attributes); +} + +function element_node(\DOMElement $element): void +{ + if ($element->hasAttribute('class')) { + $attribute = $element->getAttributeNode('class'); + echo $attribute->value; + } +} + +function element_node_attribute_fetch_via_attributes_property(\DOMElement $element): void +{ + $attribute = $element->attributes->getNamedItem('class'); + if ($attribute === null) { + return; + } + echo $attribute->value; +} + +function element_node_attribute_fetch_via_getAttributeNode(\DOMElement $element): void +{ + $attribute = $element->getAttributeNode('class'); + if ($attribute === null) { + return; + } + echo $attribute->value; +}