array( 'post' => array( 'enabled' => 1, 'days' => 90, ), 'page' => array( 'enabled' => 1, 'days' => 180, ), ), 'excluded_terms' => array(), 'date_basis' => 'modified', // 'modified' or 'published'. 'show_list_column' => 1, 'email' => array( 'enabled' => 0, 'recipients' => array( get_option( 'admin_email' ) ), 'frequency' => 'quarterly', // 'weekly', 'monthly', 'quarterly'. 'send_day' => 1, // Weekday 1-7 or Day of month 1-28. 'send_time' => '09:00', 'max_items' => 25, 'subject' => 'Content refresh report: {stale_count} outdated items on {site_name}', 'heading' => 'Content that needs your attention', 'intro' => 'These items have not been updated within their review window.', 'footer' => 'Sent by ContentCortex from {site_name}.', 'logo_id' => 0, 'brand_color' => '#2563eb', 'button_text' => 'Open full report', 'show_columns' => array( 'type', 'days', 'author' ), 'only_if_stale' => 1, ), 'delete_on_uninstall' => 0, ); return apply_filters( 'ocap_default_settings', $defaults ); } /** * Get plugin settings merged with defaults. * * @return array */ function ocap_get_settings() { $saved = get_option( 'ocap_settings', null ); if ( null === $saved ) { // Fallback check for previous option name. $saved = get_option( 'sct_settings', array() ); } $defaults = ocap_get_default_settings(); if ( ! is_array( $saved ) ) { $saved = array(); } $settings = array_replace_recursive( $defaults, $saved ); // Ensure post_types array is well-formed. if ( isset( $saved['post_types'] ) && is_array( $saved['post_types'] ) ) { $settings['post_types'] = $saved['post_types']; } // Ensure excluded terms is array of ints. if ( isset( $saved['excluded_terms'] ) && is_array( $saved['excluded_terms'] ) ) { $settings['excluded_terms'] = array_map( 'absint', $saved['excluded_terms'] ); } // Ensure email columns is array. if ( isset( $saved['email']['show_columns'] ) && is_array( $saved['email']['show_columns'] ) ) { $settings['email']['show_columns'] = $saved['email']['show_columns']; } // Ensure email recipients is array. if ( isset( $saved['email']['recipients'] ) ) { if ( is_string( $saved['email']['recipients'] ) ) { $emails = array_map( 'trim', explode( ',', $saved['email']['recipients'] ) ); $settings['email']['recipients'] = array_filter( $emails, 'is_email' ); } elseif ( is_array( $saved['email']['recipients'] ) ) { $settings['email']['recipients'] = array_filter( array_map( 'trim', $saved['email']['recipients'] ), 'is_email' ); } } return $settings; } /** * Get a specific plugin setting. * * @param string $key Setting key. * @param mixed $default Default value if not set. * @return mixed */ function ocap_get_setting( $key, $default = null ) { $settings = ocap_get_settings(); return isset( $settings[ $key ] ) ? $settings[ $key ] : $default; } /** * Clear the stale count cache transient and object cache. */ function ocap_clear_stale_cache() { delete_transient( 'ocap_stale_count' ); delete_transient( 'sct_stale_count' ); if ( function_exists( 'wp_cache_flush_group' ) ) { wp_cache_flush_group( 'ocap_query' ); wp_cache_flush_group( 'sct_query' ); } } /** * Get total stale count, cached via transient. * * @param bool $force_refresh Whether to bypass transient cache. * @return int Stale count. */ function ocap_get_stale_count( $force_refresh = false ) { if ( ! $force_refresh ) { $cached = get_transient( 'ocap_stale_count' ); if ( false !== $cached ) { return (int) $cached; } } if ( class_exists( 'OCAP_Query' ) ) { $query = new OCAP_Query(); $count = $query->get_count(); } else { $count = 0; } set_transient( 'ocap_stale_count', $count, HOUR_IN_SECONDS ); return (int) $count; } /** * Calculate the effective date for a post. * The later of last updated (or published date depending on basis) and last reviewed. * * @param int|WP_Post $post Post ID or object. * @param string|null $date_basis Optional 'modified' or 'published'. Defaults to plugin setting. * @return string GMT datetime (Y-m-d H:i:s). */ function ocap_get_effective_date( $post, $date_basis = null ) { $post = get_post( $post ); if ( ! $post ) { return gmdate( 'Y-m-d H:i:s' ); } if ( null === $date_basis ) { $date_basis = ocap_get_setting( 'date_basis', 'modified' ); } $base_date = ( 'published' === $date_basis ) ? $post->post_date_gmt : $post->post_modified_gmt; if ( empty( $base_date ) || '0000-00-00 00:00:00' === $base_date ) { $base_date = $post->post_date_gmt; } $last_reviewed = get_post_meta( $post->ID, '_ocap_last_reviewed', true ); if ( empty( $last_reviewed ) ) { $last_reviewed = get_post_meta( $post->ID, '_sct_last_reviewed', true ); } if ( ! empty( $last_reviewed ) && '0000-00-00 00:00:00' !== $last_reviewed ) { return ( strtotime( $last_reviewed ) > strtotime( $base_date ) ) ? $last_reviewed : $base_date; } return $base_date; } /** * Calculate days since last update based on effective date. * * @param int|WP_Post $post Post ID or object. * @param string|null $date_basis Optional date basis. * @return int Days since update (whole days, floored). */ function ocap_calculate_days_since_update( $post, $date_basis = null ) { $effective_date = ocap_get_effective_date( $post, $date_basis ); $effective_time = strtotime( $effective_date . ' GMT' ); $current_time = time(); if ( ! $effective_time || $effective_time > $current_time ) { return 0; } return (int) floor( ( $current_time - $effective_time ) / DAY_IN_SECONDS ); } /** * Get day limit for a specific post type. * * @param string $post_type Post type name. * @return int Day limit, default 90. */ function ocap_get_post_type_day_limit( $post_type ) { $settings = ocap_get_settings(); $post_types = isset( $settings['post_types'] ) ? $settings['post_types'] : array(); if ( isset( $post_types[ $post_type ]['days'] ) ) { return max( 1, (int) $post_types[ $post_type ]['days'] ); } return 90; } /** * Check if a post type is enabled for stale tracking. * * @param string $post_type Post type name. * @return bool */ function ocap_is_post_type_enabled( $post_type ) { $settings = ocap_get_settings(); $post_types = isset( $settings['post_types'] ) ? $settings['post_types'] : array(); return ! empty( $post_types[ $post_type ]['enabled'] ); } /** * Get the report admin page URL. * * @param array $args Query parameters to append. * @return string */ function ocap_get_report_url( $args = array() ) { $url = admin_url( 'admin.php?page=outdated-content' ); if ( ! empty( $args ) ) { $url = add_query_arg( $args, $url ); } return $url; } /** * Get the settings admin page URL. * * @param string $tab Optional tab name. * @return string */ function ocap_get_settings_url( $tab = '' ) { $url = admin_url( 'admin.php?page=outdated-content-settings' ); if ( ! empty( $tab ) ) { $url = add_query_arg( 'tab', $tab, $url ); } return $url; }