You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
6.3 KiB
218 lines
6.3 KiB
<?php |
|
/** |
|
* Class AMP_Comments_Sanitizer. |
|
* |
|
* @package AMP |
|
*/ |
|
|
|
/** |
|
* Class AMP_Comments_Sanitizer |
|
* |
|
* Strips and corrects attributes in forms. |
|
*/ |
|
class AMP_Comments_Sanitizer extends AMP_Base_Sanitizer { |
|
|
|
/** |
|
* Default args. |
|
* |
|
* @since 1.1 |
|
* |
|
* @var array |
|
*/ |
|
protected $DEFAULT_ARGS = [ |
|
'comment_live_list' => false, |
|
]; |
|
|
|
/** |
|
* Pre-process the comment form and comment list for AMP. |
|
* |
|
* @since 0.7 |
|
*/ |
|
public function sanitize() { |
|
foreach ( $this->dom->getElementsByTagName( 'form' ) as $comment_form ) { |
|
/** |
|
* Comment form. |
|
* |
|
* @var DOMElement $comment_form |
|
*/ |
|
$action = $comment_form->getAttribute( 'action-xhr' ); |
|
if ( ! $action ) { |
|
$action = $comment_form->getAttribute( 'action' ); |
|
} |
|
$action_path = wp_parse_url( $action, PHP_URL_PATH ); |
|
if ( preg_match( '#/wp-comments-post\.php$#', $action_path ) ) { |
|
$this->process_comment_form( $comment_form ); |
|
} |
|
} |
|
|
|
if ( ! empty( $this->args['comments_live_list'] ) ) { |
|
$xpath = new DOMXPath( $this->dom ); |
|
$comments = $xpath->query( '//amp-live-list/*[ @items ]/*[ starts-with( @id, "comment-" ) ]' ); |
|
|
|
foreach ( $comments as $comment ) { |
|
$this->add_amp_live_list_comment_attributes( $comment ); |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Comment form. |
|
* |
|
* @since 0.7 |
|
* |
|
* @param DOMElement $comment_form Comment form. |
|
*/ |
|
protected function process_comment_form( $comment_form ) { |
|
/** |
|
* Element. |
|
* |
|
* @var DOMElement $element |
|
*/ |
|
|
|
/** |
|
* Named input elements. |
|
* |
|
* @var DOMElement[][] $form_fields |
|
*/ |
|
$form_fields = []; |
|
foreach ( $comment_form->getElementsByTagName( 'input' ) as $element ) { |
|
$name = $element->getAttribute( 'name' ); |
|
if ( $name ) { |
|
$form_fields[ $name ][] = $element; |
|
} |
|
} |
|
foreach ( $comment_form->getElementsByTagName( 'textarea' ) as $element ) { |
|
$name = $element->getAttribute( 'name' ); |
|
if ( $name ) { |
|
$form_fields[ $name ][] = $element; |
|
} |
|
} |
|
|
|
if ( empty( $form_fields['comment_post_ID'] ) ) { |
|
return; |
|
} |
|
$post_id = (int) $form_fields['comment_post_ID'][0]->getAttribute( 'value' ); |
|
$state_id = AMP_Theme_Support::get_comment_form_state_id( $post_id ); |
|
|
|
$form_state = [ |
|
'values' => [], |
|
'submitting' => false, |
|
'replyToName' => '', |
|
]; |
|
|
|
if ( ! empty( $form_fields['comment_parent'] ) ) { |
|
$comment_id = (int) $form_fields['comment_parent'][0]->getAttribute( 'value' ); |
|
if ( $comment_id ) { |
|
$reply_comment = get_comment( $comment_id ); |
|
if ( $reply_comment ) { |
|
$form_state['replyToName'] = $reply_comment->comment_author; |
|
} |
|
} |
|
} |
|
|
|
$amp_bind_attr_format = AMP_DOM_Utils::AMP_BIND_DATA_ATTR_PREFIX . '%s'; |
|
foreach ( $form_fields as $name => $form_field ) { |
|
foreach ( $form_field as $element ) { |
|
|
|
// @todo Radio and checkbox inputs are not supported yet. |
|
if ( in_array( strtolower( $element->getAttribute( 'type' ) ), [ 'checkbox', 'radio' ], true ) ) { |
|
continue; |
|
} |
|
|
|
$element->setAttribute( sprintf( $amp_bind_attr_format, 'disabled' ), "$state_id.submitting" ); |
|
|
|
if ( 'textarea' === strtolower( $element->nodeName ) ) { |
|
$form_state['values'][ $name ] = $element->textContent; |
|
$element->setAttribute( sprintf( $amp_bind_attr_format, 'text' ), "$state_id.values.$name" ); |
|
} else { |
|
$form_state['values'][ $name ] = $element->hasAttribute( 'value' ) ? $element->getAttribute( 'value' ) : ''; |
|
$element->setAttribute( sprintf( $amp_bind_attr_format, 'value' ), "$state_id.values.$name" ); |
|
} |
|
|
|
// Update the state in response to changing the input. |
|
$element->setAttribute( |
|
'on', |
|
sprintf( |
|
'change:AMP.setState( { %s: { values: { %s: event.value } } } )', |
|
$state_id, |
|
wp_json_encode( $name ) |
|
) |
|
); |
|
} |
|
} |
|
|
|
// Add amp-state to the document. |
|
$amp_state = $this->dom->createElement( 'amp-state' ); |
|
$amp_state->setAttribute( 'id', $state_id ); |
|
$script = $this->dom->createElement( 'script' ); |
|
$script->setAttribute( 'type', 'application/json' ); |
|
$amp_state->appendChild( $script ); |
|
$script->appendChild( $this->dom->createTextNode( wp_json_encode( $form_state, JSON_UNESCAPED_UNICODE ) ) ); |
|
$comment_form->insertBefore( $amp_state, $comment_form->firstChild ); |
|
|
|
// Update state when submitting form. |
|
$form_reset_state = $form_state; |
|
unset( |
|
$form_reset_state['values']['author'], |
|
$form_reset_state['values']['email'], |
|
$form_reset_state['values']['url'] |
|
); |
|
$on = [ |
|
// Disable the form when submitting. |
|
sprintf( |
|
'submit:AMP.setState( { %s: { submitting: true } } )', |
|
wp_json_encode( $state_id ) |
|
), |
|
// Re-enable the form fields when the submission fails. |
|
sprintf( |
|
'submit-error:AMP.setState( { %s: { submitting: false } } )', |
|
wp_json_encode( $state_id ) |
|
), |
|
// Reset the form to its initial state (with enabled form fields), except for the author, email, and url. |
|
sprintf( |
|
'submit-success:AMP.setState( { %s: %s } )', |
|
$state_id, |
|
wp_json_encode( $form_reset_state, JSON_UNESCAPED_UNICODE ) |
|
), |
|
]; |
|
$comment_form->setAttribute( 'on', implode( ';', $on ) ); |
|
} |
|
|
|
/** |
|
* Add attributes to comment elements when comments are being presented in amp-live-list, when comments_live_list theme support flag is present. |
|
* |
|
* @since 1.1 |
|
* |
|
* @param DOMElement $comment_element Comment element. |
|
*/ |
|
protected function add_amp_live_list_comment_attributes( $comment_element ) { |
|
$comment_id = (int) str_replace( 'comment-', '', $comment_element->getAttribute( 'id' ) ); |
|
if ( ! $comment_id ) { |
|
return; |
|
} |
|
$comment_object = get_comment( $comment_id ); |
|
|
|
// Skip if the comment is not valid or the comment has a parent, since in that case it is not relevant for amp-live-list. |
|
if ( ! ( $comment_object instanceof WP_Comment ) || $comment_object->comment_parent ) { |
|
return; |
|
} |
|
|
|
$comment_element->setAttribute( 'data-sort-time', strtotime( $comment_object->comment_date ) ); |
|
|
|
$update_time = strtotime( $comment_object->comment_date ); |
|
|
|
// Ensure the top-level data-update-time reflects the max time of the comments in the thread. |
|
$children = $comment_object->get_children( |
|
[ |
|
'format' => 'flat', |
|
'hierarchical' => 'flat', |
|
'orderby' => 'none', |
|
] |
|
); |
|
foreach ( $children as $child_comment ) { |
|
$update_time = max( strtotime( $child_comment->comment_date ), $update_time ); |
|
} |
|
|
|
$comment_element->setAttribute( 'data-update-time', $update_time ); |
|
} |
|
}
|
|
|