Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UI to select an offline page #28

Merged
merged 31 commits into from
Jul 27, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
314c472
Begin UI to select an offline page.
kienstra Jul 11, 2018
596e44c
Add UI field description and improve settings field title.
hellofromtonya Jul 11, 2018
225ba95
Change option name to `page_for_offline`.
hellofromtonya Jul 12, 2018
53f6533
Add the post state message for the offline page.
hellofromtonya Jul 12, 2018
8d7aa1c
Made settings errors appear on loading the Reading page.
hellofromtonya Jul 12, 2018
7d7da59
Remove the page attributes meta box from only the Offline Page.
hellofromtonya Jul 12, 2018
c683eaf
Remove page attributes support for Offline Page.
hellofromtonya Jul 13, 2018
e76b7f1
Optimize the admin initialization by registering one callback.
hellofromtonya Jul 13, 2018
83c5604
Improve the method names to tell intent.
hellofromtonya Jul 13, 2018
98c6f82
Exclude static pages from dropdowns.
hellofromtonya Jul 13, 2018
7e6574b
Add create new page functionality.
hellofromtonya Jul 13, 2018
c403da5
Merge 'master' to update feature branch.
hellofromtonya Jul 13, 2018
6a7a720
Fix plugin dir constant after master merge.
hellofromtonya Jul 13, 2018
cc997ef
Re-enable page attributes.
hellofromtonya Jul 16, 2018
33c461c
Excluding offline page from menus and search.
hellofromtonya Jul 16, 2018
c7c96b4
Exclude the offline page from Customizer's homepage & posts page drop…
hellofromtonya Jul 16, 2018
c48b36c
Exclude offline page from rendering on frontend.
hellofromtonya Jul 16, 2018
05b655b
Split tasks into separate classes.
hellofromtonya Jul 17, 2018
7104c53
Improve and optimize excluder.
hellofromtonya Jul 17, 2018
cc40e00
Apply changes based on code review
westonruter Jul 26, 2018
846ce07
Include privacy page in `get_static_pages()`.
Jul 26, 2018
11b49fc
Improve tests to ensure privacy page is also excluded from the offlin…
Jul 26, 2018
40f8737
Change settings label to "Default offline status page".
Jul 26, 2018
7ef0dea
Publish status only in the page dropdowns and for creating a new page.
Jul 26, 2018
eddeb84
Merge the offline page ID with the current "post__not_in" var.
Jul 26, 2018
d1dbaf9
Offline page is a page and singular.
Jul 26, 2018
f8c3137
Improve is_offline_page_query().
Jul 26, 2018
ab4cbc6
Allow the default offline page to load on the frontend.
Jul 26, 2018
03e78ba
Make naming more clear by adding "default".
Jul 26, 2018
9669026
Exclude the default offline page from robots.
Jul 26, 2018
af9aedd
Separate concerns for no robots. Code formatting.
Jul 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions pwa.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@
/** WP_Service_Workers Class */
require PWA_PLUGIN_DIR . '/wp-includes/class-wp-service-workers.php';

/** WP_Offline_Page Class */
require PWA_PLUGIN_DIR . '/wp-includes/class-wp-offline-page.php';

/** WordPress Service Worker Functions */
require PWA_PLUGIN_DIR . '/wp-includes/service-workers.php';

/** Amend default filters */
require PWA_PLUGIN_DIR . '/wp-includes/default-filters.php';

/** WP_Offline_Page Class */
require PWA_PLUGIN_DIR . '/wp-includes/class-wp-offline-page.php';

$wp_web_app_manifest = new WP_Web_App_Manifest();
$wp_web_app_manifest->init();
$wp_https_detection = new WP_HTTPS_Detection();
Expand Down
21 changes: 6 additions & 15 deletions tests/test-class-wp-offline-page-ui.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function setUp() {
public function test_init() {
$this->instance->init();
$this->assertEquals( 10, has_action( 'admin_init', array( $this->instance, 'init_admin' ) ) );
$this->assertEquals( 10, has_action( 'admin_action_create-offline-page', array( $this->instance, 'create_new_page' ) ) );
$this->assertEquals( 10, has_action( 'admin_action_create-offline-page', array( $this->instance, 'handle_create_offline_page_action' ) ) );
$this->assertEquals( 10, has_action( 'admin_notices', array( $this->instance, 'add_settings_error' ) ) );
$this->assertEquals( 10, has_filter( 'display_post_states', array( $this->instance, 'add_post_state' ) ) );
}
Expand Down Expand Up @@ -176,8 +176,7 @@ public function test_render_settings() {
// Check that it excludes the configured static pages.
update_option( 'page_on_front', (int) $page_ids[0] );
update_option( 'page_for_posts', (int) $page_ids[1] );
update_option( 'wp_page_for_privacy_policy', (int) $page_ids[2] );
$this->manager->get_static_pages( true );
update_option( WP_Offline_Page::OPTION_NAME, (int) $page_ids[2] );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mistakenly equated wp_page_for_privacy_policy with WP_Offline_Page::OPTION_NAME here.

ob_start();
$this->instance->render_settings();
$output = ob_get_clean();
Expand All @@ -196,15 +195,12 @@ public function test_render_settings() {
* @covers WP_Offline_Page::create_new_page()
*/
public function test_create_new_page() {
add_filter( 'wp_redirect', '__return_empty_string' );
// Check on the wrong page.
set_current_screen( 'edit.php' );
$this->assertFalse( $this->instance->create_new_page() );

$this->assertEquals( 0, get_option( WP_Offline_Page::OPTION_NAME, 0 ) );
set_current_screen( 'options-reading.php' );
$this->assertNull( $this->instance->create_new_page() );
$offline_id = (int) get_option( WP_Offline_Page::OPTION_NAME, 0 );
$page_id = $this->instance->create_new_page();
$this->assertInternalType( 'int', $page_id );
$offline_id = (int) get_option( WP_Offline_Page::OPTION_NAME, 0 );
$this->assertEquals( $page_id, $offline_id );
$offline_page = get_post( $offline_id );
$this->assertGreaterThan( 0, $offline_id );
$this->assertInstanceOf( 'WP_Post', $offline_page );
Expand Down Expand Up @@ -266,7 +262,6 @@ public function test_add_settings_error() {

// Check when no offline page is passed (e.g. doing 'admin_notices') and the offline page has been configured but does not exist.
update_option( WP_Offline_Page::OPTION_NAME, 999999 );
$this->manager->get_offline_page_id( true );
$this->assertTrue( $this->instance->add_settings_error() );
$this->assertEquals(
array_merge(
Expand All @@ -285,7 +280,6 @@ public function test_add_settings_error() {
'post_status' => 'trash',
) );
update_option( WP_Offline_Page::OPTION_NAME, $trashed_page->ID );
$this->manager->get_offline_page_id( true );
$this->assertTrue( $this->instance->add_settings_error() );
$this->assertEquals(
array_merge(
Expand All @@ -301,7 +295,6 @@ public function test_add_settings_error() {
// Check when no offline page is passed (e.g. doing 'admin_notices') and the offline page is configured.
$offline_page_id = $this->factory()->post->create( array( 'post_type' => 'page' ) );
update_option( WP_Offline_Page::OPTION_NAME, $offline_page_id );
$this->manager->get_offline_page_id( true );
$this->assertFalse( $this->instance->add_settings_error() );
$this->assertEquals( array(), $wp_settings_errors );
}
Expand All @@ -316,11 +309,9 @@ public function test_add_post_state() {
$this->assertEmpty( $this->instance->add_post_state( array(), $page ) );

add_option( WP_Offline_Page::OPTION_NAME, $page->ID );
$this->manager->get_offline_page_id( true );
$this->assertSame( array( 'Offline Page' ), $this->instance->add_post_state( array(), $page ) );

update_option( WP_Offline_Page::OPTION_NAME, $page->ID + 10 );
$this->manager->get_offline_page_id( true );
$this->assertEmpty( $this->instance->add_post_state( array(), $page ) );
}
}
3 changes: 0 additions & 3 deletions tests/test-class-wp-offline-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public function setUp() {
*/
public function test_init() {
$this->instance->init();
$this->assertEquals( 10, has_action( 'admin_init', array( $this->instance, 'init_admin' ) ) );
}

/**
Expand All @@ -44,10 +43,8 @@ public function test_init() {
*/
public function test_get_offline_page_id() {
$this->assertSame( 0, $this->instance->get_offline_page_id() );
$this->assertSame( 0, $this->instance->get_offline_page_id( true ) );

add_option( WP_Offline_Page::OPTION_NAME, 5 );
$this->assertSame( 5, $this->instance->get_offline_page_id() );
$this->assertSame( 5, $this->instance->get_offline_page_id( true ) );
}
}
11 changes: 4 additions & 7 deletions wp-includes/class-wp-offline-page-excluder.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,15 @@ public function init() {
*
* @param string $html HTML output for drop down list of pages.
* @param array $args The parsed arguments array.
*
* @return string
* @return string Filtered content for wp_dropdown_pages.
*/
public function exclude_from_page_dropdown( $html, $args ) {
// Bail out if this is the offline page dropdown.
if ( WP_Offline_Page::OPTION_NAME === $args['name'] ) {
return $html;
}

return preg_replace( '/<option .* value="' . $this->manager->get_offline_page_id() . '">.*<\/option>/', '', $html );
return preg_replace( '/<option .*? value="' . $this->manager->get_offline_page_id() . '">.*?<\/option>/', '', $html );
}

/**
Expand All @@ -71,8 +70,7 @@ public function exclude_from_query( WP_Query $query ) {
* Checks if the query is for the offline page.
*
* @param WP_Query $query The WP_Query instance.
*
* @return bool
* @return bool Whether an offline page query.
*/
protected function is_offline_page_query( WP_Query $query ) {
if ( $query->is_admin ) {
Expand All @@ -90,8 +88,7 @@ protected function is_offline_page_query( WP_Query $query ) {
* Checks if the offline page should be excluded or not.
*
* @param WP_Query $query The WP_Query instance.
*
* @return bool
* @return bool OK to exclude.
*/
protected function is_okay_to_exclude( WP_Query $query ) {
// All searches should be excluded.
Expand Down
110 changes: 55 additions & 55 deletions wp-includes/class-wp-offline-page-ui.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function __construct( $manager ) {
*/
public function init() {
add_action( 'admin_init', array( $this, 'init_admin' ) );
add_action( 'admin_action_create-offline-page', array( $this, 'create_new_page' ) );
add_action( 'admin_action_create-offline-page', array( $this, 'handle_create_offline_page_action' ) );
add_action( 'admin_notices', array( $this, 'add_settings_error' ) );
add_filter( 'display_post_states', array( $this, 'add_post_state' ), 10, 2 );
}
Expand Down Expand Up @@ -77,7 +77,6 @@ public function register_setting() {
* Sanitize callback for the setting.
*
* @param string $raw_setting The setting before sanitizing it.
*
* @return string|null The sanitized setting, or null if it's invalid.
*/
public function sanitize_callback( $raw_setting ) {
Expand All @@ -87,6 +86,7 @@ public function sanitize_callback( $raw_setting ) {
if ( false === $this->add_settings_error( $offline_page ) ) {
return $sanitized_post_id;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return the DB-saved value so as to not blow away what is there already.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe not. It could be that the DB option is no longer valid either.

return null;
}

/**
Expand Down Expand Up @@ -138,6 +138,9 @@ public function render_settings() {
* Renders the page dropdown.
*/
protected function render_page_dropdown() {
$non_offline_static_pages = $this->manager->get_static_pages();
unset( $non_offline_static_pages[ WP_Offline_Page::OPTION_NAME ] );

wp_dropdown_pages(
array(
'name' => esc_html( WP_Offline_Page::OPTION_NAME ),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should actually be esc_attr().

Expand All @@ -146,57 +149,72 @@ protected function render_page_dropdown() {
'option_none_value' => '0',
'selected' => intval( $this->manager->get_offline_page_id() ),
'post_status' => array( 'draft', 'publish' ),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per above, let's only include publish here.

'exclude' => esc_html( $this->get_static_pages_ids( true ) ),
'exclude' => implode( ',', $non_offline_static_pages ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.XSS.EscapeOutput.OutputNotEscaped -- This is a false positive.
)
);
}

/**
* Creates a new offline page.
* Handle the create-offline-page admin action.
*
* @return bool|null
* Will redirect to the newly created post upon success (and thus will not return).
*/
public function create_new_page() {
public function handle_create_offline_page_action() {

// Bail out if this is not the right page.
$screen = get_current_screen();
if ( ! $screen instanceof WP_Screen || 'options-reading' !== $screen->id ) {
return false;
return;
}

$r = $this->create_new_page();
if ( is_wp_error( $r ) ) {
add_settings_error(
WP_Offline_Page::OPTION_NAME,
WP_Offline_Page::OPTION_NAME,
__( 'Unable to create the offline page.', 'pwa' ),
'error'
);
} else {
wp_safe_redirect( get_edit_post_link( $r, 'raw' ) );
exit;
}
}

/**
* Creates a new offline page.
*
* @return int|WP_Error The page ID or WP_Error on failure.
*/
public function create_new_page() {

$page_id = wp_insert_post(
array(
'post_title' => __( 'Offline Page', 'pwa' ),
wp_slash( array(
'post_title' => __( 'Offline', 'pwa' ),
'post_status' => 'draft',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, let's have this create a publish'ed page. If we allow selecting a draft page then it wouldn't be accessible to the user.

'post_type' => 'page',
'post_content' => $this->get_default_content(),
),
) ),
true
);

if ( ! is_wp_error( $page_id ) ) {
update_option( WP_Offline_Page::OPTION_NAME, $page_id );
if ( wp_redirect( admin_url( 'post.php?post=' . $page_id . '&action=edit' ) ) ) {
exit;
}

return;
if ( is_wp_error( $page_id ) ) {
return $page_id;
}

add_settings_error(
WP_Offline_Page::OPTION_NAME,
WP_Offline_Page::OPTION_NAME,
__( 'Unable to create the offline page.', 'pwa' ),
'error'
);
update_option( WP_Offline_Page::OPTION_NAME, $page_id );
return $page_id;
}

/**
* Get the default content for a new offline page.
*
* @todo provide content here for shortcode (classic) or block (Gutenberg)
* @todo In the future this could provide a shortcode (classic) or block (Gutenberg) that lists out the URLs that are available offline.
*
* @return string Default content.
*/
protected function get_default_content() {
return '';
return "<!-- wp:paragraph -->\n<p>" . __( 'It appears either that you are offline or the site is down.', 'pwa' ) . "</p>\n<!-- /wp:paragraph -->";
}

/**
Expand Down Expand Up @@ -246,7 +264,7 @@ public function add_settings_error( $offline_page = '' ) {
/**
* When the given post is the offline page, add the state to the given post states.
*
* @since 1.0.0
* @since 0.2.0
*
* @param array $post_states An array of post display states.
* @param WP_Post $post The current post object.
Expand All @@ -261,35 +279,19 @@ public function add_post_state( array $post_states, $post ) {
return $post_states;
}

/**
* Gets the configured static pages IDs.
*
* @param bool $join Optional. When true, a comma-delimited list is returned; else, an array is returned.
*
* @return array|string
*/
protected function get_static_pages_ids( $join = false ) {
// Remove the duplicates and empties.
$static_pages = array_filter( array_unique( $this->manager->get_static_pages() ) );

if ( ! $join ) {
return $static_pages;
}

return $static_pages ? implode( ',', $static_pages ) : '';
}

/**
* Checks if there are any pages to display in the page dropdown.
*
* @return boolean
* @return bool Whether there are pages to show in the dropdown.
*/
protected function has_pages() {
$query = new WP_Query( array(
'post_type' => 'page',
'posts_per_page' => 1,
'post_status' => array( 'publish', 'draft' ),
'post__not_in' => $this->get_static_pages_ids(), // exclude the static pages.
'post_type' => 'page',
'posts_per_page' => 1,
'post_status' => array( 'publish', 'draft' ),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per above, let's only include publish here.

'post__not_in' => array_filter( $this->manager->get_static_pages() ), // exclude the static pages.
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
) );

return $query->found_posts > 0;
Expand All @@ -299,11 +301,10 @@ protected function has_pages() {
* Check if the offline page does not exist.
*
* @param WP_Post|int $offline_page The offline page to check.
*
* @return bool
* @return bool Whether page does not exist.
*/
protected function does_not_exist( $offline_page ) {
if ( is_int( $offline_page ) ) {
if ( is_int( $offline_page ) && $offline_page > 0 ) {
$offline_page = get_post( $offline_page );
}

Expand All @@ -314,11 +315,10 @@ protected function does_not_exist( $offline_page ) {
* Check if the offline page is in the trash.
*
* @param WP_Post|int $offline_page The offline page to check.
*
* @return bool
* @return bool Whether the page is in the trash.
*/
protected function is_in_trash_error( $offline_page ) {
if ( is_int( $offline_page ) ) {
if ( is_int( $offline_page ) && $offline_page > 0 ) {
$offline_page = get_post( $offline_page );
}

Expand Down
Loading