Skip to content

Commit

Permalink
Don't show post enable/disable if template is not available
Browse files Browse the repository at this point in the history
Fix up some tests
Address CR feedback

[ci skip]
  • Loading branch information
westonruter committed Jun 30, 2018
1 parent 3f4ef4c commit a616e84
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 112 deletions.
34 changes: 16 additions & 18 deletions includes/admin/class-amp-post-meta-box.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,20 @@ public function enqueue_admin_assets() {
array( 'jquery' ),
AMP__VERSION
);

if ( current_theme_supports( 'amp' ) ) {
$availability = AMP_Theme_Support::get_template_availability( $post );
$support_errors = $availability['errors'];
} else {
$support_errors = AMP_Post_Type_Support::get_support_errors( $post );
}

wp_add_inline_script( self::ASSETS_HANDLE, sprintf( 'ampPostMetaBox.boot( %s );',
wp_json_encode( array(
'previewLink' => esc_url_raw( add_query_arg( amp_get_slug(), '', get_preview_post_link( $post ) ) ),
'canonical' => amp_is_canonical(),
'enabled' => post_supports_amp( $post ),
'canSupport' => count( AMP_Post_Type_Support::get_support_errors( $post ) ) === 0,
'enabled' => empty( $support_errors ),
'canSupport' => 0 === count( array_diff( $support_errors, array( 'post-status-disabled' ) ) ),
'statusInputName' => self::STATUS_INPUT_NAME,
'l10n' => array(
'ampPreviewBtnLabel' => __( 'Preview changes in AMP (opens in new window)', 'amp' ),
Expand All @@ -170,7 +178,6 @@ public function render_status( $post ) {
is_post_type_viewable( $post->post_type )
&&
current_user_can( 'edit_post', $post->ID )
// @todo What if a site does not have non-AMP pages? Formerly this was indicated via amp_is_canonical(). Now we need a flag for whether AMP is exclusive to a theme, in which case all templates and post types must render AMP. In other words, all_templates_supported.
);

if ( true !== $verify ) {
Expand All @@ -181,23 +188,14 @@ public function render_status( $post ) {
$status = empty( $errors ) ? self::ENABLED_STATUS : self::DISABLED_STATUS;
$errors = array_diff( $errors, array( 'post-status-disabled' ) ); // Subtract the status which the metabox will allow to be toggled.

// @todo If ! supported and immutable, don't show the toggle at all?
// Handle special case of the static front page or page for posts.
if ( current_theme_supports( 'amp' ) ) {

$query = new WP_Query();
if ( 'page' === $post->post_type ) {
$query->set( 'page_id', $post->ID );
} else {
$query->set( 'p', $post->ID );
}
$query->queried_object = $post;
$query->queried_object_id = $post->ID;
$query->parse_query_vars();

$availability = AMP_Theme_Support::get_template_availability( $query );
if ( $availability instanceof WP_Error && 0 !== count( array_diff( $availability->get_error_codes(), $errors, array( 'post-status-disabled' ) ) ) ) {
$errors[] = 'template-unavailable';
$availability = AMP_Theme_Support::get_template_availability( $post );
if ( true === $availability['immutable'] ) {
$errors[] = 'status_immutable';
$status = $availability['supported'] ? self::ENABLED_STATUS : self::DISABLED_STATUS;
} elseif ( ! $availability['supported'] && in_array( 'template_unsupported', $availability['errors'], true ) ) {
$errors[] = 'template_unsupported';
$status = self::DISABLED_STATUS;
}
}
Expand Down
31 changes: 10 additions & 21 deletions includes/amp-helper-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,14 @@ function post_supports_amp( $post ) {
* Determine whether the current response being served as AMP.
*
* This function cannot be called before the parse_query action because it needs to be able
* to determine the queried object is able to be served as AMP.
* to determine the queried object is able to be served as AMP. If 'amp' theme support is not
* present, this function returns true just if the query var is present. If theme support is
* present, then it returns true in paired mode if an AMP template is available and the query
* var is present, or else in native mode if just the template is available.
*
* @see is_header_video_active()
* @return bool Whether it is the AMP endpoint.
*/
function is_amp_endpoint() {
global $wp_query;
if ( is_admin() || is_feed() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
return false;
}
Expand All @@ -272,29 +273,17 @@ function is_amp_endpoint() {
false !== get_query_var( amp_get_slug(), false )
);

if ( ! current_theme_supports( 'amp' ) ) {
return $has_amp_query_var;
}

// When there is no query var and AMP is not canonical/native, then this is definitely not an AMP endpoint.
if ( ! $has_amp_query_var && ! amp_is_canonical() ) {
return false;
}

if ( current_theme_supports( 'amp' ) ) {
$template_available = true === AMP_Theme_Support::get_template_availability();
return amp_is_canonical() ? $template_available : $has_amp_query_var;
} else {

// Check if the queried object supports AMP.
if ( is_singular() || ( $wp_query instanceof WP_Query && $wp_query->is_posts_page ) ) {
/**
* Post.
*
* @var WP_Post $queried_object
*/
$queried_object = get_queried_object();
return post_supports_amp( $queried_object );
}

return false; // Legacy templates only support posts via AMP_Post_Template.
}
$availability = AMP_Theme_Support::get_template_availability();
return amp_is_canonical() ? $availability['supported'] : ( $has_amp_query_var && $availability['supported'] );
}

/**
Expand Down
116 changes: 89 additions & 27 deletions includes/class-amp-theme-support.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public static function init() {
}

/**
* Determine whether theme support as added via option.
* Determine whether theme support was added via option.
*
* @since 1.0
* @return bool Optional support added.
Expand Down Expand Up @@ -177,6 +177,10 @@ public static function apply_options() {
}
}

if ( ! $theme_support_args ) {
$theme_support_args = array();
}

// If theme support is not present, then allow it to be added via the admin.
if ( ! current_theme_supports( 'amp' ) ) {
if ( 'disabled' === $theme_support_option ) {
Expand Down Expand Up @@ -317,11 +321,7 @@ public static function is_paired_available() {
}

$availability = self::get_template_availability();
if ( is_wp_error( $availability ) ) {
return false;
}

return true;
return $availability['supported'];
}

/**
Expand Down Expand Up @@ -354,24 +354,59 @@ public static function add_amp_template_filters() {
* @global WP_Query $wp_query
* @see post_supports_amp()
*
* @param WP_Query|null $query Query or queried post. If null then the global query will be used.
* @return true|WP_Error True if template is available, WP_Error if otherwise.
* @param WP_Query|WP_Post|null $query Query or queried post. If null then the global query will be used.
* @return array {
* Template availability.
*
* @type bool $supported Whether the template is supported in AMP.
* @type bool|null $immutable Whether the supported status is known to be unchangeable.
* @type string|null $template The ID of the matched template (conditional), such as 'is_singular', or null if nothing was matched.
* @type string[] $errors List of the errors or reasons for why the template is not available.
* }
*/
public static function get_template_availability( $query = null ) {
global $wp_query;
if ( ! $query ) {
$query = $wp_query;
} elseif ( $query instanceof WP_Post ) {
$post = $query;
$query = new WP_Query();
if ( 'page' === $post->post_type ) {
$query->set( 'page_id', $post->ID );
} else {
$query->set( 'p', $post->ID );
}
$query->queried_object = $post;
$query->queried_object_id = $post->ID;
$query->parse_query_vars();
}

$default_response = array(
'errors' => array(),
'supported' => false,
'immutable' => null,
'template' => null,
);

if ( ! ( $query instanceof WP_Query ) ) {
_doing_it_wrong( __FUNCTION__, esc_html__( 'No WP_Query available.', 'amp' ), '1.0' );
return new WP_Error( 'no_query_available' );
return array_merge(
$default_response,
array( 'errors' => array( 'no_query_available' ) )
);
}

if ( ! current_theme_supports( 'amp' ) ) {
return new WP_Error( 'no_theme_support' );
return array_merge(
$default_response,
array( 'errors' => array( 'no_theme_support' ) )
);
}

// Make sure global $wp_query is set in case of conditionals that unfortunately look at global scope.
$prev_query = $wp_query;
$wp_query = $query; // WPCS: override ok.

$matching_templates = array();
$supportable_templates = self::get_supportable_templates();
foreach ( $supportable_templates as $id => $supportable_template ) {
Expand All @@ -381,23 +416,33 @@ public static function get_template_availability( $query = null ) {
$callback = $supportable_template['callback'];
}

// @todo Consider using the $id as the conditional callback.
// If the available_callback is a method on the query, then call the method on the query itself.
if ( is_string( $callback ) && 'is_' === substr( $callback, 0, 3 ) && method_exists( $query, $callback ) ) {
$is_match = call_user_func( array( $query, $callback ) );
} else {
} elseif ( is_callable( $callback ) ) {
$is_match = call_user_func( $callback );
} else {
/* translators: %s is the supportable template ID. */
_doing_it_wrong( __FUNCTION__, esc_html__( 'Supportable template "%s" does not have a callable callback.', 'amp' ), '1.0' );
$is_match = false;
}

if ( $is_match ) {
$matching_templates[ $id ] = (
! empty( $supportable_template['supported'] )
||
( AMP_Options_Manager::get_option( 'all_templates_supported' ) && empty( $supportable_template['immutable'] ) )
$matching_templates[ $id ] = array(
'template' => $id,
'supported' => (
! empty( $supportable_template['supported'] )
||
( AMP_Options_Manager::get_option( 'all_templates_supported' ) && empty( $supportable_template['immutable'] ) )
),
'immutable' => ! empty( $supportable_template['immutable'] ),
);
}
}

// Restore previous $wp_query (if any).
$wp_query = $prev_query; // WPCS: override ok.

// Make sure children override their parents.
$matching_template_ids = array_keys( $matching_templates );
foreach ( $matching_template_ids as $id ) {
Expand Down Expand Up @@ -425,9 +470,24 @@ public static function get_template_availability( $query = null ) {
}
}

if ( count( $matching_templates ) > 1 ) {
_doing_it_wrong( __FUNCTION__, esc_html__( 'Did not expect there to be more than one matching template. Did you filter amp_supportable_templates to not honor the template hierarchy?', 'amp' ), '1.0' );
}

$matching_template = array_shift( $matching_templates );

// If there aren't any matching templates left that are supported, then we consider it to not be available.
if ( ! in_array( true, $matching_templates, true ) ) {
return new WP_Error( 'no_supported_template' );
if ( ! $matching_template ) {
return array_merge(
$default_response,
array( 'errors' => array( 'no_matching_template' ) )
);
}
$matching_template = array_merge( $default_response, $matching_template );

// If there aren't any matching templates left that are supported, then we consider it to not be available.
if ( empty( $matching_template['supported'] ) ) {
$matching_template['errors'][] = 'template_unsupported';
}

// For singular queries, post_supports_amp() is given the final say.
Expand All @@ -440,16 +500,12 @@ public static function get_template_availability( $query = null ) {
$queried_object = $query->get_queried_object();
$support_errors = AMP_Post_Type_Support::get_support_errors( $queried_object );
if ( ! empty( $support_errors ) ) {
$error = new WP_Error();
foreach ( $support_errors as $support_error ) {
$error->add( $support_error, '' );
}
return $error;
$matching_template['errors'] = array_merge( $matching_template['errors'], $support_errors );
$matching_template['supported'] = false;
}
}

// If all checks have passed, then the template is available.
return true;
return $matching_template;
}

/**
Expand Down Expand Up @@ -560,7 +616,13 @@ public static function get_supportable_templates() {
*
* A theme or plugin can force a given template to be supported or not by preemptively
* setting the 'supported' flag for a given template. Otherwise, if the flag is undefined
* then the user will be able to toggle it themselves in the admin.
* then the user will be able to toggle it themselves in the admin. Each array item should
* have a key that corresponds to a template conditional function. If the key is such a
* function, then the key is used to evaluate whether the given template entry is a match.
* Otherwise, a supportable template item can include a callback value which is used instead.
* Each item needs a 'label' value. Additionally, if the supportable template is a subset of
* another condition (e.g. is_singular > is_single) then this relationship needs to be
* indicated via the 'parent' value.
*
* @since 1.0
*
Expand All @@ -572,7 +634,7 @@ public static function get_supportable_templates() {
foreach ( $templates as $id => &$template ) {
$template['immutable'] = isset( $template['supported'] );
if ( ! $template['immutable'] ) {
$template['supported'] = in_array( $id, $supported_templates, true );
$template['supported'] = AMP_Options_Manager::get_option( 'all_templates_supported' ) || in_array( $id, $supported_templates, true );
}
}

Expand Down
4 changes: 2 additions & 2 deletions includes/options/class-amp-options-menu.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public function render_supported_templates() {
<?php $element_name = AMP_Options_Manager::OPTION_NAME . '[supported_post_types][]'; ?>
<h4 class="title"><?php esc_html_e( 'Content Types', 'amp' ); ?></h4>
<p>
<?php esc_html_e( 'The following content types will be available as AMP by default, but you can override this on an item-by-item basis:', 'amp' ); ?>
<?php esc_html_e( 'The following content types will be available as AMP:', 'amp' ); ?>
</p>
<ul>
<?php foreach ( array_map( 'get_post_type_object', AMP_Post_Type_Support::get_eligible_post_types() ) as $post_type ) : ?>
Expand All @@ -310,7 +310,7 @@ public function render_supported_templates() {
id="<?php echo esc_attr( $element_id ); ?>"
name="<?php echo esc_attr( $element_name ); ?>"
value="<?php echo esc_attr( $post_type->name ); ?>"
<?php checked( true, post_type_supports( $post_type->name, amp_get_slug() ) ); ?>
<?php checked( post_type_supports( $post_type->name, amp_get_slug() ) ); ?>
>
<label for="<?php echo esc_attr( $element_id ); ?>">
<?php echo esc_html( $post_type->label ); ?>
Expand Down
8 changes: 7 additions & 1 deletion includes/validation/class-amp-validation-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,13 @@ public static function is_sanitization_forcibly_accepted() {
* @param WP_Admin_Bar $wp_admin_bar Admin bar.
*/
public static function add_admin_bar_menu_items( $wp_admin_bar ) {
if ( is_admin() || ! self::has_cap() || is_wp_error( AMP_Theme_Support::get_template_availability() ) ) {
if ( is_admin() || ! self::has_cap() ) {
self::$amp_admin_bar_item_added = false;
return;
}

$availability = AMP_Theme_Support::get_template_availability();
if ( ! $availability['supported'] ) {
self::$amp_admin_bar_item_added = false;
return;
}
Expand Down
11 changes: 9 additions & 2 deletions templates/admin/amp-status.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,14 @@
<p>
<?php
$error_messages = array();
if ( in_array( 'template-unavailable', $errors, true ) ) {
if ( in_array( 'status_immutable', $errors, true ) ) {
if ( self::ENABLED_STATUS === $status ) {
$error_messages[] = __( 'Your site does not allow AMP to be disabled.', 'amp' );
} else {
$error_messages[] = __( 'Your site does not allow AMP to be enabled.', 'amp' );
}
}
if ( in_array( 'template_unsupported', $errors, true ) ) {
/* translators: %s is URL to AMP settings screen */
$error_messages[] = wp_kses_post( sprintf( __( 'There are no <a href="%s">supported templates</a> to display this in AMP.', 'amp' ), esc_url( admin_url( 'admin.php?page=' . AMP_Options_Manager::OPTION_NAME ) ) ) );
}
Expand All @@ -56,7 +63,7 @@
if ( in_array( 'skip-post', $errors, true ) ) {
$error_messages[] = __( 'A plugin or theme has disabled AMP support.', 'amp' );
}
if ( count( array_diff( $errors, array( 'page-on-front', 'page-for-posts', 'password-protected', 'post-type-support', 'skip-post', 'template-unavailable' ) ) ) > 0 ) {
if ( count( array_diff( $errors, array( 'status_immutable', 'page-on-front', 'page-for-posts', 'password-protected', 'post-type-support', 'skip-post', 'template_unsupported' ) ) ) > 0 ) {
$error_messages[] = __( 'Unavailable for an unknown reason.', 'amp' );
}
echo implode( ' ', $error_messages ); // WPCS: xss ok.
Expand Down
Loading

0 comments on commit a616e84

Please sign in to comment.