'post_published', 'id' => 'post_published:' . $post->ID, 'occurred_at' => gmdate( 'c' ), 'title' => self::title( $post ), 'url' => get_permalink( $post ), 'post_type' => $post->post_type, ) ); } /** * Something already live was edited. * * @param int $post_id Post ID. * @param WP_Post $post_after The post now. * @param WP_Post $post_before The post before the edit. */ public static function on_update( $post_id, $post_after, $post_before ) { if ( 'publish' !== $post_after->post_status || 'publish' !== $post_before->post_status ) { return; } $changed = $post_after->post_title !== $post_before->post_title || $post_after->post_content !== $post_before->post_content || $post_after->post_excerpt !== $post_before->post_excerpt; if ( ! $changed ) { return; } if ( 'wp_navigation' === $post_after->post_type ) { self::menu_saved( 'wp_navigation:' . $post_id, $post_after->post_title ); } elseif ( 'wp_global_styles' === $post_after->post_type ) { self::on_design_saved(); } elseif ( self::is_template( $post_after ) ) { self::template_saved( $post_after ); } else { self::edited( $post_after ); } } /** * A page builder saved a layout. Drafts and revisions don't count; a live page does. * * @param int $meta_id Meta row ID. * @param int $post_id Post ID. * @param string $meta_key The field. */ public static function on_layout_saved( $meta_id, $post_id, $meta_key ) { if ( ! in_array( $meta_key, self::layout_meta(), true ) ) { return; } $post = get_post( $post_id ); if ( ! $post || 'publish' !== $post->post_status ) { return; } if ( self::is_template( $post ) ) { self::template_saved( $post ); } else { self::edited( $post ); } } /** * A classic menu was saved (Appearance > Menus or the Customizer). * * @param int $menu_id Menu term ID. */ public static function on_menu_saved( $menu_id ) { $menu = wp_get_nav_menu_object( $menu_id ); self::menu_saved( 'nav_menu:' . (int) $menu_id, $menu ? $menu->name : '' ); } /** * The theme's design settings changed: the Customizer, or Styles in the Site Editor. * One event a day. */ public static function on_design_saved() { Monthwrap_Store::record( array( 'type' => 'design_updated', 'id' => 'design_updated:' . current_time( 'Y-m-d' ), 'occurred_at' => gmdate( 'c' ), 'name' => mb_substr( (string) wp_get_theme()->get( 'Name' ), 0, 200 ), ) ); } /** * A live item was edited: one event per item per day, none on its publish day. * * @param WP_Post $post The post. */ private static function edited( $post ) { if ( ! self::tracked( $post ) ) { return; } $today = current_time( 'Y-m-d' ); if ( get_the_date( 'Y-m-d', $post ) === $today ) { return; } $type = 'page' === $post->post_type ? 'page_updated' : 'post_updated'; Monthwrap_Store::record( array( 'type' => $type, 'id' => $type . ':' . $post->ID . ':' . $today, 'occurred_at' => gmdate( 'c' ), 'title' => self::title( $post ), 'url' => get_permalink( $post ), 'post_type' => $post->post_type, ) ); } /** * A template was created or changed: one event per template per day. * * @param WP_Post $post The template. */ private static function template_saved( $post ) { if ( wp_is_post_revision( $post ) || wp_is_post_autosave( $post ) ) { return; } Monthwrap_Store::record( array( 'type' => 'template_updated', 'id' => 'template_updated:' . $post->ID . ':' . current_time( 'Y-m-d' ), 'occurred_at' => gmdate( 'c' ), 'name' => mb_substr( self::title( $post ), 0, 200 ), ) ); } /** * A menu was changed: one event per menu per day. * * @param string $key Which menu. * @param string $name The menu's name. */ private static function menu_saved( $key, $name ) { Monthwrap_Store::record( array( 'type' => 'menu_updated', 'id' => 'menu_updated:' . $key . ':' . current_time( 'Y-m-d' ), 'occurred_at' => gmdate( 'c' ), 'name' => mb_substr( '' !== trim( $name ) ? $name : __( 'Menu', 'monthwrap' ), 0, 200 ), ) ); } /** * Whether a post is a theme or page builder template. * * @param WP_Post $post The post. * @return bool */ private static function is_template( $post ) { /** * Filters the post types treated as templates rather than content. * * @param string[] $types Post type names. */ $types = (array) apply_filters( 'monthwrap_template_post_types', self::TEMPLATE_TYPES ); return in_array( $post->post_type, $types, true ); } /** * The layout fields watched for page builder edits. * * @return string[] */ private static function layout_meta() { /** * Filters the post meta keys where page builders store a page's layout. * * @param string[] $keys Meta keys. */ return (array) apply_filters( 'monthwrap_layout_meta_keys', self::LAYOUT_META ); } /** * Whether a post counts as client-visible content: public types only, never revisions, * autosaves, media or templates. * * @param WP_Post $post The post. * @return bool */ private static function tracked( $post ) { if ( ! $post instanceof WP_Post || wp_is_post_revision( $post ) || wp_is_post_autosave( $post ) ) { return false; } $type = get_post_type_object( $post->post_type ); $tracked = $type && $type->public && 'attachment' !== $post->post_type && ! self::is_template( $post ); /** * Filters whether a post's publishing and edits are sent to Monthwrap. * * @param bool $tracked Whether it's sent. * @param WP_Post $post The post. */ return (bool) apply_filters( 'monthwrap_track_post', $tracked, $post ); } /** * The post's title as plain text. * * @param WP_Post $post The post. * @return string */ private static function title( $post ) { $title = html_entity_decode( wp_strip_all_tags( get_the_title( $post ) ), ENT_QUOTES, 'UTF-8' ); if ( '' === trim( $title ) ) { $title = __( '(no title)', 'monthwrap' ); } return mb_substr( $title, 0, 300 ); } }