157 lines
4.9 KiB
PHP
157 lines
4.9 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* What makes publishing a post also publish it to the name.
|
||
|
|
*
|
||
|
|
* Everything hangs off `transition_post_status`, which fires for every way a
|
||
|
|
* post can change state — the editor, quick edit, a scheduled publish firing
|
||
|
|
* from cron, the REST API, WP-CLI, an importer. Hooking `save_post` instead
|
||
|
|
* would miss the scheduled case, which is exactly the case a site owner most
|
||
|
|
* expects to work while they are asleep.
|
||
|
|
*
|
||
|
|
* Unpublishing is handled too, and it matters more than it looks: a static
|
||
|
|
* mirror that keeps serving a post the author deleted is worse than no mirror,
|
||
|
|
* because the author believes the page is gone.
|
||
|
|
*
|
||
|
|
* @package SiriusPress
|
||
|
|
*/
|
||
|
|
|
||
|
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
|
||
|
|
final class SPE_Hooks {
|
||
|
|
|
||
|
|
public static function hooks() {
|
||
|
|
add_action( 'transition_post_status', array( __CLASS__, 'on_transition' ), 10, 3 );
|
||
|
|
add_action( 'before_delete_post', array( __CLASS__, 'on_delete' ), 10, 2 );
|
||
|
|
add_action( 'edited_term', array( __CLASS__, 'on_term_edited' ), 10, 3 );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param string $new_status
|
||
|
|
* @param string $old_status
|
||
|
|
* @param WP_Post $post
|
||
|
|
*/
|
||
|
|
public static function on_transition( $new_status, $old_status, $post ) {
|
||
|
|
if ( ! self::should_export( $post ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Went from public to not — take the file down before refreshing the
|
||
|
|
// pages that used to link to it.
|
||
|
|
if ( 'publish' === $old_status && 'publish' !== $new_status ) {
|
||
|
|
$path = SPE_Mapper::path_for_post( $post );
|
||
|
|
if ( '' !== $path ) {
|
||
|
|
self::unpublish( $path );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( 'publish' !== $new_status && 'publish' !== $old_status ) {
|
||
|
|
return; // A draft being edited changes nothing anyone can see.
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ( SPE_Mapper::affected_by_post( $post ) as $path => $target ) {
|
||
|
|
SPE_Queue::add( $path, $target['url'], $target['kind'] );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function on_delete( $post_id, $post = null ) {
|
||
|
|
$post = $post ? $post : get_post( $post_id );
|
||
|
|
if ( ! $post || ! self::should_export( $post ) || 'publish' !== $post->post_status ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
$path = SPE_Mapper::path_for_post( $post );
|
||
|
|
if ( '' !== $path ) {
|
||
|
|
self::unpublish( $path );
|
||
|
|
}
|
||
|
|
foreach ( SPE_Mapper::affected_by_post( $post ) as $affected => $target ) {
|
||
|
|
if ( $affected !== $path ) {
|
||
|
|
SPE_Queue::add( $affected, $target['url'], $target['kind'] );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Renaming a category changes its archive URL and every page linking to it. */
|
||
|
|
public static function on_term_edited( $term_id, $tt_id, $taxonomy ) {
|
||
|
|
if ( ! SP_Settings::auto_publish() ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
$tax = get_taxonomy( $taxonomy );
|
||
|
|
if ( ! $tax || ! $tax->public ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
$link = get_term_link( (int) $term_id, $taxonomy );
|
||
|
|
if ( is_wp_error( $link ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
$path = SPE_Mapper::path_for_url_path( (string) wp_parse_url( $link, PHP_URL_PATH ) );
|
||
|
|
if ( '' !== $path ) {
|
||
|
|
SPE_Queue::add( $path, $link, 'archive' );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static function should_export( $post ) {
|
||
|
|
if ( ! SP_Settings::auto_publish() || ! SP_Settings::is_configured() ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if ( ! $post instanceof WP_Post ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if ( wp_is_post_revision( $post ) || wp_is_post_autosave( $post ) ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
$type = get_post_type_object( $post->post_type );
|
||
|
|
if ( ! $type || ! $type->public ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
// A password-protected post renders as a password form to the
|
||
|
|
// exporter, and publishing that form to permanent public storage
|
||
|
|
// would be worse than not publishing at all.
|
||
|
|
if ( '' !== $post->post_password ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Filters whether a post is exported at all.
|
||
|
|
*
|
||
|
|
* @param bool $export
|
||
|
|
* @param WP_Post $post
|
||
|
|
*/
|
||
|
|
return (bool) apply_filters( 'sirius_press_should_export_post', true, $post );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Remove a path from the bucket.
|
||
|
|
*
|
||
|
|
* In manual mode there is no key to sign a delete with, so the operator is
|
||
|
|
* told rather than left with a stale page they think is gone.
|
||
|
|
*/
|
||
|
|
private static function unpublish( $path ) {
|
||
|
|
if ( SP_Settings::MODE_SERVER !== SP_Settings::mode() ) {
|
||
|
|
SP_Inbox::add(
|
||
|
|
0,
|
||
|
|
__( 'A removed page is still published to your name', 'sirius-press' ),
|
||
|
|
sprintf(
|
||
|
|
/* translators: 1: bucket path, 2: export screen URL. */
|
||
|
|
wp_kses_post( __( '<code>%1$s</code> is no longer public on this site, but this server holds no key to delete it from the name\'s storage. <a href="%2$s">Remove it from the export screen</a>.', 'sirius-press' ) ),
|
||
|
|
esc_html( $path ),
|
||
|
|
esc_url( admin_url( 'admin.php?page=sirius-press-export' ) )
|
||
|
|
),
|
||
|
|
'export'
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
$result = SP_Gateway::delete( $path );
|
||
|
|
if ( empty( $result['ok'] ) ) {
|
||
|
|
SP_Inbox::add(
|
||
|
|
0,
|
||
|
|
__( 'A removed page could not be unpublished', 'sirius-press' ),
|
||
|
|
sprintf(
|
||
|
|
/* translators: 1: bucket path, 2: error message. */
|
||
|
|
wp_kses_post( __( '<code>%1$s</code> could not be deleted from the name\'s storage: %2$s', 'sirius-press' ) ),
|
||
|
|
esc_html( $path ),
|
||
|
|
esc_html( $result['error'] )
|
||
|
|
),
|
||
|
|
'export'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|