Skip to content

Commit 95bde01

Browse files
authored
Merge pull request #5388 from ampproject/fix/keeping-component-scripts-for-kept-invalid-markup
Gather required script components even for kept invalid markup
2 parents f8cc996 + cdcb9e2 commit 95bde01

File tree

1 file changed

+37
-27
lines changed

1 file changed

+37
-27
lines changed

includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -573,34 +573,34 @@ static function ( $validation_error ) {
573573
}
574574
}
575575

576+
$attr_spec_list = array_merge(
577+
$this->globally_allowed_attributes,
578+
$attr_spec_list
579+
);
580+
576581
// Remove element if it has illegal CDATA.
577582
if ( ! empty( $cdata ) && $node instanceof DOMElement ) {
578583
$validity = $this->validate_cdata_for_node( $node, $cdata );
579584
if ( true !== $validity ) {
580-
$this->remove_invalid_child(
585+
$sanitized = $this->remove_invalid_child(
581586
$node,
582587
array_merge(
583588
$validity,
584589
[ 'spec_name' => $this->get_spec_name( $node, $tag_spec ) ]
585590
)
586591
);
587-
return null;
592+
return $sanitized ? null : $this->get_required_script_components( $node, $tag_spec, $attr_spec_list );
588593
}
589594
}
590595

591-
$merged_attr_spec_list = array_merge(
592-
$this->globally_allowed_attributes,
593-
$attr_spec_list
594-
);
595-
596596
// Amend spec list with layout.
597597
if ( isset( $tag_spec['amp_layout'] ) ) {
598-
$merged_attr_spec_list = array_merge( $merged_attr_spec_list, $this->layout_allowed_attributes );
598+
$attr_spec_list = array_merge( $attr_spec_list, $this->layout_allowed_attributes );
599599

600600
if ( isset( $tag_spec['amp_layout']['supported_layouts'] ) ) {
601601
$layouts = wp_array_slice_assoc( Layout::FROM_SPEC, $tag_spec['amp_layout']['supported_layouts'] );
602602

603-
$merged_attr_spec_list['layout'][ AMP_Rule_Spec::VALUE_REGEX_CASEI ] = '(' . implode( '|', $layouts ) . ')';
603+
$attr_spec_list['layout'][ AMP_Rule_Spec::VALUE_REGEX_CASEI ] = '(' . implode( '|', $layouts ) . ')';
604604
}
605605
}
606606

@@ -626,12 +626,12 @@ static function ( $validation_error ) {
626626
// Remove the element if it is has an invalid layout.
627627
$layout_validity = $this->is_valid_layout( $tag_spec, $node );
628628
if ( true !== $layout_validity ) {
629-
$this->remove_invalid_child( $node, $layout_validity );
630-
return null;
629+
$sanitized = $this->remove_invalid_child( $node, $layout_validity );
630+
return $sanitized ? null : $this->get_required_script_components( $node, $tag_spec, $attr_spec_list );
631631
}
632632

633633
// Identify attribute values that don't conform to the attr_spec.
634-
$disallowed_attributes = $this->sanitize_disallowed_attribute_values_in_node( $node, $merged_attr_spec_list );
634+
$disallowed_attributes = $this->sanitize_disallowed_attribute_values_in_node( $node, $attr_spec_list );
635635

636636
// Remove all invalid attributes.
637637
if ( ! empty( $disallowed_attributes ) ) {
@@ -679,7 +679,7 @@ static function ( $validation_error ) {
679679

680680
if ( $this->should_sanitize_validation_error( $validation_error, [ 'node' => $attr_node ] ) ) {
681681
$properties = $this->parse_properties_attribute( $attr_node->nodeValue );
682-
if ( ! empty( $merged_attr_spec_list[ $attr_node->nodeName ]['value_properties'][ $error_data['name'] ]['mandatory'] ) ) {
682+
if ( ! empty( $attr_spec_list[ $attr_node->nodeName ]['value_properties'][ $error_data['name'] ]['mandatory'] ) ) {
683683
$properties[ $error_data['name'] ] = $error_data['required_value'];
684684
} else {
685685
unset( $properties[ $error_data['name'] ] );
@@ -697,7 +697,7 @@ static function ( $validation_error ) {
697697
$node->setAttribute( $attr_node->nodeName, $this->serialize_properties_attribute( $properties ) );
698698
}
699699
} else {
700-
$attr_spec = isset( $merged_attr_spec_list[ $attr_node->nodeName ] ) ? $merged_attr_spec_list[ $attr_node->nodeName ] : [];
700+
$attr_spec = isset( $attr_spec_list[ $attr_node->nodeName ] ) ? $attr_spec_list[ $attr_node->nodeName ] : [];
701701
if ( $this->remove_invalid_attribute( $node, $attr_node, $validation_error, $attr_spec ) ) {
702702
$removed_attributes[] = $attr_node;
703703
}
@@ -726,71 +726,82 @@ static function ( $validation_error ) {
726726
}
727727

728728
// After attributes have been sanitized (and potentially removed), if mandatory attribute(s) are missing, remove the element.
729-
$missing_mandatory_attributes = $this->get_missing_mandatory_attributes( $merged_attr_spec_list, $node );
729+
$missing_mandatory_attributes = $this->get_missing_mandatory_attributes( $attr_spec_list, $node );
730730
if ( ! empty( $missing_mandatory_attributes ) ) {
731-
$this->remove_invalid_child(
731+
$sanitized = $this->remove_invalid_child(
732732
$node,
733733
[
734734
'code' => self::ATTR_REQUIRED_BUT_MISSING,
735735
'attributes' => $missing_mandatory_attributes,
736736
'spec_name' => $this->get_spec_name( $node, $tag_spec ),
737737
]
738738
);
739-
return null;
739+
return $sanitized ? null : $this->get_required_script_components( $node, $tag_spec, $attr_spec_list );
740740
}
741741

742742
if ( ! empty( $tag_spec[ AMP_Rule_Spec::MANDATORY_ANYOF ] ) ) {
743743
$anyof_attributes = $this->get_element_attribute_intersection( $node, $tag_spec[ AMP_Rule_Spec::MANDATORY_ANYOF ] );
744744
if ( 0 === count( $anyof_attributes ) ) {
745-
$this->remove_invalid_child(
745+
$sanitized = $this->remove_invalid_child(
746746
$node,
747747
[
748748
'code' => self::MANDATORY_ANYOF_ATTR_MISSING,
749749
'mandatory_anyof_attrs' => $tag_spec[ AMP_Rule_Spec::MANDATORY_ANYOF ], // @todo Temporary as value can be looked up via spec name. See https://github.com/ampproject/amp-wp/pull/3817.
750750
'spec_name' => $this->get_spec_name( $node, $tag_spec ),
751751
]
752752
);
753-
return null;
753+
return $sanitized ? null : $this->get_required_script_components( $node, $tag_spec, $attr_spec_list );
754754
}
755755
}
756756

757757
if ( ! empty( $tag_spec[ AMP_Rule_Spec::MANDATORY_ONEOF ] ) ) {
758758
$oneof_attributes = $this->get_element_attribute_intersection( $node, $tag_spec[ AMP_Rule_Spec::MANDATORY_ONEOF ] );
759759
if ( 0 === count( $oneof_attributes ) ) {
760-
$this->remove_invalid_child(
760+
$sanitized = $this->remove_invalid_child(
761761
$node,
762762
[
763763
'code' => self::MANDATORY_ONEOF_ATTR_MISSING,
764764
'mandatory_oneof_attrs' => $tag_spec[ AMP_Rule_Spec::MANDATORY_ONEOF ], // @todo Temporary as value can be looked up via spec name. See https://github.com/ampproject/amp-wp/pull/3817.
765765
'spec_name' => $this->get_spec_name( $node, $tag_spec ),
766766
]
767767
);
768-
return null;
768+
return $sanitized ? null : $this->get_required_script_components( $node, $tag_spec, $attr_spec_list );
769769
} elseif ( count( $oneof_attributes ) > 1 ) {
770-
$this->remove_invalid_child(
770+
$sanitized = $this->remove_invalid_child(
771771
$node,
772772
[
773773
'code' => self::DUPLICATE_ONEOF_ATTRS,
774774
'duplicate_oneof_attrs' => $oneof_attributes,
775775
'spec_name' => $this->get_spec_name( $node, $tag_spec ),
776776
]
777777
);
778-
return null;
778+
return $sanitized ? null : $this->get_required_script_components( $node, $tag_spec, $attr_spec_list );
779779
}
780780
}
781781

782-
// Add required AMP component scripts.
782+
return $this->get_required_script_components( $node, $tag_spec, $attr_spec_list );
783+
}
784+
785+
/**
786+
* Get required AMP component scripts.
787+
*
788+
* @param DOMElement $node Element.
789+
* @param array $tag_spec Tag spec.
790+
* @param array $attr_spec_list Attribute spec list.
791+
* @return string[] Script component handles.
792+
*/
793+
private function get_required_script_components( DOMElement $node, $tag_spec, $attr_spec_list ) {
783794
$script_components = [];
784795
if ( ! empty( $tag_spec['requires_extension'] ) ) {
785796
$script_components = array_merge( $script_components, $tag_spec['requires_extension'] );
786797
}
787798

788799
// Add required AMP components for attributes.
789800
foreach ( $node->attributes as $attribute ) {
790-
if ( isset( $merged_attr_spec_list[ $attribute->nodeName ]['requires_extension'] ) ) {
801+
if ( isset( $attr_spec_list[ $attribute->nodeName ]['requires_extension'] ) ) {
791802
$script_components = array_merge(
792803
$script_components,
793-
$merged_attr_spec_list[ $attribute->nodeName ]['requires_extension']
804+
$attr_spec_list[ $attribute->nodeName ]['requires_extension']
794805
);
795806
}
796807
}
@@ -809,7 +820,6 @@ static function ( $validation_error ) {
809820
}
810821
}
811822
}
812-
813823
return $script_components;
814824
}
815825

0 commit comments

Comments
 (0)