AnsPress_Hooks()
Description #
Register common anspress hooks
Source #
File: includes/hooks.php
class AnsPress_Hooks {
/**
* Menu class.
*
* @var string
*/
public static $menu_class = '';
/**
* Initialize the class
*
* @since 2.0.1
* @since 2.4.8 Removed `$ap` argument.
*/
public static function init() {
anspress()->add_action( 'registered_taxonomy', __CLASS__, 'add_ap_tables' );
anspress()->add_action( 'ap_processed_new_question', __CLASS__, 'after_new_question', 1, 2 );
anspress()->add_action( 'ap_processed_new_answer', __CLASS__, 'after_new_answer', 1, 2 );
anspress()->add_action( 'before_delete_post', __CLASS__, 'before_delete' );
anspress()->add_action( 'wp_trash_post', __CLASS__, 'trash_post_action' );
anspress()->add_action( 'untrash_post', __CLASS__, 'untrash_posts' );
anspress()->add_action( 'comment_post', __CLASS__, 'new_comment_approve', 10, 2 );
anspress()->add_action( 'comment_unapproved_to_approved', __CLASS__, 'comment_approve' );
anspress()->add_action( 'comment_approved_to_unapproved', __CLASS__, 'comment_unapprove' );
anspress()->add_action( 'trashed_comment', __CLASS__, 'comment_trash' );
anspress()->add_action( 'delete_comment', __CLASS__, 'comment_trash' );
anspress()->add_action( 'edit_comment', __CLASS__, 'edit_comment' );
anspress()->add_action( 'ap_publish_comment', __CLASS__, 'publish_comment' );
anspress()->add_action( 'ap_unpublish_comment', __CLASS__, 'unpublish_comment' );
anspress()->add_action( 'wp_loaded', __CLASS__, 'flush_rules' );
anspress()->add_action( 'safe_style_css', __CLASS__, 'safe_style_css', 11 );
anspress()->add_action( 'save_post', __CLASS__, 'base_page_update', 10, 2 );
anspress()->add_action( 'save_post_question', __CLASS__, 'save_question_hooks', 1, 3 );
anspress()->add_action( 'save_post_answer', __CLASS__, 'save_answer_hooks', 1, 3 );
anspress()->add_action( 'transition_post_status', __CLASS__, 'transition_post_status', 10, 3 );
anspress()->add_action( 'ap_vote_casted', __CLASS__, 'update_user_vote_casted_count', 10, 4 );
anspress()->add_action( 'ap_vote_removed', __CLASS__, 'update_user_vote_casted_count', 10, 4 );
anspress()->add_action( 'ap_display_question_metas', __CLASS__, 'display_question_metas', 100, 2 );
anspress()->add_action( 'widget_comments_args', __CLASS__, 'widget_comments_args' );
anspress()->add_filter( 'posts_clauses', 'AP_QA_Query_Hooks', 'sql_filter', 1, 2 );
anspress()->add_filter( 'posts_results', 'AP_QA_Query_Hooks', 'posts_results', 1, 2 );
anspress()->add_filter( 'posts_pre_query', 'AP_QA_Query_Hooks', 'modify_main_posts', 999999, 2 );
anspress()->add_filter( 'pre_get_posts', 'AP_QA_Query_Hooks', 'pre_get_posts' );
// Theme hooks.
anspress()->add_action( 'init', 'AnsPress_Theme', 'init_actions' );
anspress()->add_filter( 'template_include', 'AnsPress_Theme', 'template_include' );
anspress()->add_filter( 'ap_template_include', 'AnsPress_Theme', 'template_include_theme_compat' );
anspress()->add_filter( 'post_class', 'AnsPress_Theme', 'question_answer_post_class' );
anspress()->add_filter( 'body_class', 'AnsPress_Theme', 'body_class' );
anspress()->add_action( 'after_setup_theme', 'AnsPress_Theme', 'includes_theme' );
anspress()->add_filter( 'wp_title', 'AnsPress_Theme', 'ap_title', 0 );
anspress()->add_filter( 'document_title_parts', 'AnsPress_Theme', 'ap_title_parts', 0 );
anspress()->add_action( 'ap_before', 'AnsPress_Theme', 'ap_before_html_body' );
anspress()->add_action( 'wp_head', 'AnsPress_Theme', 'wp_head', 11 );
anspress()->add_action( 'ap_after_question_content', 'AnsPress_Theme', 'question_attachments', 11 );
anspress()->add_action( 'ap_after_answer_content', 'AnsPress_Theme', 'question_attachments', 11 );
anspress()->add_filter( 'nav_menu_css_class', __CLASS__, 'fix_nav_current_class', 10, 2 );
anspress()->add_filter( 'wp_insert_post_data', __CLASS__, 'wp_insert_post_data', 1000, 2 );
anspress()->add_filter( 'ap_form_contents_filter', __CLASS__, 'sanitize_description' );
anspress()->add_filter( 'template_include', 'AnsPress_Theme', 'anspress_basepage_template', 9999 );
anspress()->add_filter( 'get_the_excerpt', 'AnsPress_Theme', 'get_the_excerpt', 9999, 2 );
anspress()->add_filter( 'post_class', 'AnsPress_Theme', 'remove_hentry_class', 10, 3 );
anspress()->add_action( 'ap_after_question_content', 'AnsPress_Theme', 'after_question_content' );
anspress()->add_filter( 'ap_after_answer_content', 'AnsPress_Theme', 'after_question_content' );
anspress()->add_filter( 'the_comments', 'AnsPress_Comment_Hooks', 'the_comments' );
anspress()->add_filter( 'get_comment_link', 'AnsPress_Comment_Hooks', 'comment_link', 10, 3 );
anspress()->add_filter( 'preprocess_comment', 'AnsPress_Comment_Hooks', 'preprocess_comment' );
anspress()->add_filter( 'comments_template', 'AnsPress_Comment_Hooks', 'comments_template' );
// Common pages hooks.
anspress()->add_action( 'init', 'AnsPress_Common_Pages', 'register_common_pages' );
// Register post status.
anspress()->add_action( 'init', 'AnsPress_Post_Status', 'register_post_status' );
// Rewrite rules hooks.
anspress()->add_filter( 'request', 'AnsPress_Rewrite', 'alter_the_query' );
anspress()->add_filter( 'query_vars', 'AnsPress_Rewrite', 'query_var' );
anspress()->add_action( 'generate_rewrite_rules', 'AnsPress_Rewrite', 'rewrites', 1 );
anspress()->add_filter( 'paginate_links', 'AnsPress_Rewrite', 'pagination_fix' );
anspress()->add_filter( 'parse_request', 'AnsPress_Rewrite', 'add_query_var' );
anspress()->add_action( 'template_redirect', 'AnsPress_Rewrite', 'shortlink' );
// Upload hooks.
anspress()->add_action( 'deleted_post', 'AnsPress_Uploader', 'deleted_attachment' );
anspress()->add_action( 'init', 'AnsPress_Uploader', 'create_single_schedule' );
anspress()->add_action( 'ap_delete_temp_attachments', 'AnsPress_Uploader', 'cron_delete_temp_attachments' );
anspress()->add_action( 'intermediate_image_sizes_advanced', 'AnsPress_Uploader', 'image_sizes_advanced' );
// Vote hooks.
anspress()->add_action( 'ap_before_delete_question', 'AnsPress_Vote', 'delete_votes' );
anspress()->add_action( 'ap_before_delete_answer', 'AnsPress_Vote', 'delete_votes' );
anspress()->add_action( 'ap_deleted_votes', 'AnsPress_Vote', 'ap_deleted_votes', 10, 2 );
// Form hooks.
anspress()->add_action( 'ap_form_question', 'AP_Form_Hooks', 'question_form', 11 );
anspress()->add_action( 'ap_form_answer', 'AP_Form_Hooks', 'answer_form', 11 );
anspress()->add_action( 'ap_form_comment', 'AP_Form_Hooks', 'comment_form', 11 );
anspress()->add_action( 'ap_form_image_upload', 'AP_Form_Hooks', 'image_upload_form', 11 );
// Subscriptions.
anspress()->add_action( 'ap_after_new_question', __CLASS__, 'question_subscription', 10, 2 );
anspress()->add_action( 'ap_after_new_answer', __CLASS__, 'answer_subscription', 10, 2 );
anspress()->add_action( 'ap_new_subscriber', __CLASS__, 'new_subscriber', 10, 4 );
anspress()->add_action( 'ap_delete_subscribers', __CLASS__, 'delete_subscribers', 10, 2 );
anspress()->add_action( 'ap_delete_subscriber', __CLASS__, 'delete_subscriber', 10, 3 );
anspress()->add_action( 'before_delete_post', __CLASS__, 'delete_subscriptions' );
anspress()->add_action( 'ap_publish_comment', __CLASS__, 'comment_subscription' );
anspress()->add_action( 'deleted_comment', __CLASS__, 'delete_comment_subscriptions', 10, 2 );
anspress()->add_action( 'get_comments_number', __CLASS__, 'get_comments_number', 11, 2 );
}
/**
* Add AnsPress tables in $wpdb.
*/
public static function add_ap_tables() {
ap_append_table_names();
}
/**
* Things to do after creating a question
*
* @param integer $post_id Question id.
* @param object $post Question post object.
* @since 1.0
* @since 4.1.2 Removed @see ap_update_post_activity_meta().
*/
public static function after_new_question( $post_id, $post ) {
/**
* Action triggered after inserting a question
*
* @since 0.9
*/
do_action( 'ap_after_new_question', $post_id, $post );
}
/**
* Things to do after creating an answer
*
* @param integer $post_id answer id.
* @param object $post answer post object.
* @since 2.0.1
* @since 4.1.2 Removed @see ap_update_post_activity_meta().
* @since 4.1.11 Removed @see ap_update_answers_count().
*/
public static function after_new_answer( $post_id, $post ) {
// Update answer count.
ap_update_answers_count( $post->post_parent );
/**
* Action triggered after inserting an answer
*
* @since 0.9
*/
do_action( 'ap_after_new_answer', $post_id, $post );
}
/**
* This callback handles pre delete question actions.
*
* Before deleting a question we have to make sure that all answers
* and metas are cleared. Some hooks in answer may require question data
* so its better to delete all answers before deleting question.
*
* @param integer $post_id Question or answer ID.
* @since unknown
* @since 4.1.6 Delete cache for `ap_is_answered`.
* @since 4.1.8 Delete uploaded images and `anspress-images` meta.
*/
public static function before_delete( $post_id ) {
$post = ap_get_post( $post_id );
if ( ! ap_is_cpt( $post ) ) {
return;
}
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
// Initialize WP_Filesystem.
if ( ! WP_Filesystem() ) {
// Unable to initialize WP_Filesystem, handle error accordingly.
return;
}
global $wp_filesystem;
// Get anspress uploads.
$images = get_post_meta( $post_id, 'anspress-image' );
if ( ! empty( $images ) ) {
// Delete all uploaded images.
foreach ( $images as $img ) {
$uploads = wp_upload_dir();
$file = $uploads['basedir'] . "/anspress-uploads/$img";
if ( file_exists( $file ) ) {
$wp_filesystem->delete( $file );
}
}
}
if ( 'question' === $post->post_type ) {
/**
* Action triggered before deleting a question form database.
*
* At this point question are not actually deleted from database hence
* it will be easy to perform actions which uses mysql queries.
*
* @param integer $post_id Question id.
* @param WP_Post $post Question object.
* @since unknown
*/
do_action( 'ap_before_delete_question', $post->ID, $post );
$answers = get_posts( [ 'post_parent' => $post->ID, 'post_type' => 'answer', 'post_status' => get_post_stati() ] ); // @codingStandardsIgnoreLine
if ( ap_opt( 'deleting_question_with_answer' ) && $answers ) {
ap_send_json(
array(
'success' => false,
'snackbar' => array(
'message' => esc_html__( 'Sorry, you are not allowed to delete the question permanently if there are answers available.', 'anspress-question-answer' ),
),
)
);
}
foreach ( (array) $answers as $a ) {
self::delete_answer( $a->ID, $a );
wp_delete_post( $a->ID, true );
}
// Delete qameta.
ap_delete_qameta( $post->ID );
} elseif ( 'answer' === $post->post_type ) {
self::delete_answer( $post_id, $post );
}
}
/**
* Delete answer.
*
* @param integer $post_id Question or answer ID.
* @param object $post Post Object.
* @since unknown
* @since 4.1.2 Removed @see ap_update_post_activity_meta().
*/
public static function delete_answer( $post_id, $post ) {
do_action( 'ap_before_delete_answer', $post->ID, $post );
if ( ap_is_selected( $post ) ) {
ap_unset_selected_answer( $post->post_parent );
}
// Delete qameta.
ap_delete_qameta( $post->ID );
}
/**
* If a question is sent to trash, then move its answers to trash as well
*
* @param integer $post_id Post ID.
* @since 2.0.0
* @since 4.1.2 Removed @see ap_update_post_activity_meta().
* @since 4.1.6 Delete cache for `ap_is_answered`.
*/
public static function trash_post_action( $post_id ) {
$post = ap_get_post( $post_id );
if ( 'question' === $post->post_type ) {
do_action( 'ap_trash_question', $post->ID, $post );
// Save current post status so that it can be restored.
update_post_meta( $post->ID, '_ap_last_post_status', $post->post_status );
//@codingStandardsIgnoreStart
$ans = get_posts( array(
'post_type' => 'answer',
'post_status' => 'publish',
'post_parent' => $post_id,
'showposts' => -1,
));
//@codingStandardsIgnoreEnd
if ( ap_opt( 'trashing_question_with_answer' ) && $ans ) {
ap_send_json(
array(
'success' => false,
'snackbar' => array(
'message' => esc_html__( 'Sorry, you are not allowed to trash the question if there are answers available.', 'anspress-question-answer' ),
),
)
);
}
foreach ( (array) $ans as $p ) {
$selcted_answer = ap_selected_answer();
if ( $selcted_answer === $p->ID ) {
ap_unset_selected_answer( $p->post_parent );
}
wp_trash_post( $p->ID );
}
}
if ( 'answer' === $post->post_type ) {
/**
* Triggered before trashing an answer.
*
* @param integer $post_id Answer ID.
* @param object $post Post object.
*/
do_action( 'ap_trash_answer', $post->ID, $post );
// Save current post status so that it can be restored.
update_post_meta( $post->ID, '_ap_last_post_status', $post->post_status );
ap_update_answers_count( $post->post_parent );
}
}
/**
* If questions is restored then restore its answers too.
*
* @param integer $post_id Post ID.
* @since 2.0.0
* @since 4.1.2 Removed @see ap_update_post_activity_meta().
* @since 4.1.11 Renamed method from `untrash_ans_on_question_untrash` to `untrash_posts`.
*/
public static function untrash_posts( $post_id ) {
$_post = ap_get_post( $post_id );
if ( 'question' === $_post->post_type ) {
do_action( 'ap_untrash_question', $_post->ID, $_post );
//@codingStandardsIgnoreStart
$ans = get_posts( array(
'post_type' => 'answer',
'post_status' => 'trash',
'post_parent' => $post_id,
'showposts' => -1,
));
//@codingStandardsIgnoreStart
foreach ( (array) $ans as $p ) {
//do_action( 'ap_untrash_answer', $p->ID, $p );
wp_untrash_post( $p->ID );
}
}
if ( 'answer' === $_post->post_type ) {
$ans = ap_count_published_answers( $_post->post_parent );
do_action( 'ap_untrash_answer', $_post->ID, $_post );
// Update answer count.
ap_update_answers_count( $_post->post_parent, $ans + 1 );
}
}
/**
* Used to create an action when comment publishes.
*
* @param integer $comment_id Comment ID.
* @param integer|false $approved 1 if comment is approved else false.
*
* @since unknown
* @since 4.1.0 Do not check post_type, instead comment type.
*/
public static function new_comment_approve( $comment_id, $approved ) {
if ( 1 === $approved ) {
$comment = get_comment( $comment_id );
if ( 'anspress' === $comment->comment_type ) {
/**
* Action is triggered when a anspress comment is published.
*
* @param object $comment Comment object.
* @since unknown
*/
do_action( 'ap_publish_comment', $comment );
}
}
}
/**
* Used to create an action when comment get approved.
*
* @param array|object $comment Comment object.
*
* @since unknown
* @since 4.1.0 Do not check post_type, instead comment type.
*/
public static function comment_approve( $comment ) {
if ( 'anspress' === $comment->comment_type ) {
/** This action is documented in includes/hooks.php */
do_action( 'ap_publish_comment', $comment );
}
}
/**
* Used to create an action when comment get unapproved.
*
* @param array|object $comment Comment object.
* @since unknown
* @since 4.1.0 Do not check post_type, instead comment type.
*/
public static function comment_unapprove( $comment ) {
if ( 'anspress' === $comment->comment_type ) {
/**
* Action is triggered when a anspress comment is unpublished.
*
* @param object $comment Comment object.
* @since unknown
*/
do_action( 'ap_unpublish_comment', $comment );
}
}
/**
* Used to create an action when comment get trashed.
*
* @param integer $comment_id Comment ID.
* @since unknown
* @since 4.1.0 Do not check post_type, instead comment type.
*/
public static function comment_trash( $comment_id ) {
$comment = get_comment( $comment_id );
if ( 'anspress' === $comment->comment_type ) {
/** This action is documented in includes/hooks.php */
do_action( 'ap_unpublish_comment', $comment );
}
}
/**
* Actions to run after posting a comment
*
* @param object|array $comment Comment object.
* @since unknown
* @since 4.1.2 Log to activity table on new comment. Removed @see ap_update_post_activity_meta().
*/
public static function publish_comment( $comment ) {
$comment = (object) $comment;
$post = ap_get_post( $comment->comment_post_ID );
if ( ! in_array( $post->post_type, [ 'question', 'answer' ], true ) ) {
return false;
}
$count = get_comment_count( $comment->comment_post_ID );
ap_insert_qameta( $comment->comment_post_ID, array(
'fields' => [ 'unapproved_comments' => $count['awaiting_moderation'] ],
'last_updated' => current_time( 'mysql' ),
) );
// Log to activity table.
ap_activity_add( array(
'q_id' => 'answer' === $post->post_type ? $post->post_parent: $post->ID,
'action' => 'new_c',
'a_id' => 'answer' === $post->post_type ? $post->ID: 0,
'c_id' => $comment->comment_ID,
'user_id' => $comment->user_id,
) );
}
/**
* Actions to run after unpublishing a comment.
*
* @param object|array $comment Comment object.
* @since 4.1.2 Removed @see ap_update_post_activity_meta().
*/
public static function unpublish_comment( $comment ) {
$comment = (object) $comment;
$count = get_comment_count( $comment->comment_post_ID );
ap_insert_qameta( $comment->comment_post_ID, [ 'fields' => [ 'unapproved_comments' => $count['awaiting_moderation'] ] ] );
}
/**
* Edit comment hook callback.
*
* @since unknown
* @since 4.1.2 Removed @see ap_update_post_activity_meta().
*/
public static function edit_comment( $comment_id ) {
$comment = get_comment( $comment_id );
$post = ap_get_post( $comment->comment_post_ID );
if ( ! ap_is_cpt( $post ) ) {
return;
}
$q_id = 'answer' === $post->post_type ? $post->post_parent : $post->ID;
$a_id = 'answer' === $post->post_type ? $post->ID : 0;
// Insert activity.
ap_activity_add( array(
'q_id' => $q_id,
'a_id' => $a_id,
'action' => 'edit_c',
'c_id' => $comment_id,
) );
}
/**
* Add current-menu-item class in AnsPress pages
*
* @param array $class Menu class.
* @param object $item Current menu item.
* @return array menu item.
* @since 2.1
*/
public static function fix_nav_current_class( $class, $item ) {
// Return if empty or `$item` is not object.
if ( empty( $item ) || ! is_object( $item ) ) {
return $class;
}
if ( ap_current_page() === $item->object ) {
$class[] = 'current-menu-item';
}
return $class;
}
/**
* Check if flushing rewrite rule is needed
*
* @return void
*/
public static function flush_rules() {
if ( ap_opt( 'ap_flush' ) != 'false' ) {
flush_rewrite_rules( true );
ap_opt( 'ap_flush', 'false' );
}
}
/**
* Filter post so that anonymous author should not be replaced
* by current user approving post.
*
* @param array $data post data.
* @param array $args Post arguments.
* @return array
* @since 2.2
* @since 4.1.0 Fixed: `post_author` get replaced if `anonymous_name` is empty.
*
* @global object $post Global post object.
*/
public static function wp_insert_post_data( $data, $args ) {
global $post;
if ( in_array( $args['post_type'], [ 'question', 'answer' ], true ) ) {
$fields = ap_get_post_field( 'fields', $args['ID'] );
if ( ( is_object( $post ) && '0' === $post->post_author ) || ( !empty( $fields ) && !empty( $fields['anonymous_name'] ) ) ) {
$data['post_author'] = '0';
}
}
return $data;
}
/**
* Sanitize post description
*
* @param string $contents Post content.
* @return string Return sanitized post content.
*/
public static function sanitize_description( $contents ) {
$contents = ap_trim_traling_space( $contents );
return $contents;
}
/**
* Allowed CSS attributes for post_content
*
* @param array $attr Allowed CSS attributes.
* @return array
* @since 4.1.11 Fixed wrong variable name.
*/
public static function safe_style_css( $attr ) {
global $ap_kses_check; // Check if wp_kses is called by AnsPress.
if ( isset( $ap_kses_check ) && $ap_kses_check ) {
$attr = array( 'text-decoration', 'text-align' );
}
return $attr;
}
/**
* Flush rewrite rule if base page is updated.
*
* @param integer $post_id Base page ID.
* @param object $post Post object.
* @since 4.1.0 Update respective page slug in options.
*/
public static function base_page_update( $post_id, $post ) {
if ( wp_is_post_revision( $post ) ) {
return;
}
$main_pages = array_keys( ap_main_pages() );
$page_ids = [];
foreach ( $main_pages as $slug ) {
$page_ids[ ap_opt( $slug ) ] = $slug;
}
if ( in_array( $post_id, array_keys( $page_ids ) ) ) {
$current_opt = $page_ids[ $post_id ];
ap_opt( $current_opt, $post_id );
ap_opt( $current_opt . '_id', $post->post_name );
ap_opt( 'ap_flush', 'true' );
}
}
/**
* Trigger posts hooks right after saving question.
*
* @param integer $post_id Post ID.
* @param object $post Post Object
* @param boolean $updated Is updating post
* @since 4.1.0
* @since 4.1.2 Do not process if form not submitted. Insert updated to activity table.
* @since 4.1.8 Add `ap_delete_images_not_in_content`.
*/
public static function save_question_hooks( $post_id, $post, $updated ) {
if ( wp_is_post_autosave( $post ) || wp_is_post_revision( $post ) ) {
return;
}
if ( $updated ) {
// Deleted unused images from meta.
ap_delete_images_not_in_content( $post_id );
}
$form = anspress()->get_form( 'question' );
$values = $form->get_values();
$qameta = array(
'last_updated' => current_time( 'mysql' ),
'answers' => ap_count_published_answers( $post_id ),
);
// Check if anonymous post and have name.
if ( $form->is_submitted() && ! is_user_logged_in() && ap_allow_anonymous() && ! empty( $values['anonymous_name']['value'] ) ) {
$qameta['fields'] = array(
'anonymous_name' => $values['anonymous_name']['value'],
);
}
/**
* Modify qameta args which will be inserted after inserting
* or updating question.
*
* @param array $qameta Qameta arguments.
* @param object $post Post object.
* @param boolean $updated Is updated.
* @since 4.1.0
*/
$qameta = apply_filters( 'ap_insert_question_qameta', $qameta, $post, $updated );
ap_insert_qameta( $post_id, $qameta );
if ( $updated ) {
/**
* Action triggered right after updating question.
*
* @param integer $post_id Inserted post ID.
* @param object $post Inserted post object.
* @since 0.9
* @since 4.1.0 Removed `$post->post_type` variable.
*/
do_action( 'ap_processed_update_question' , $post_id, $post );
} else {
/**
* Action triggered right after inserting new question.
*
* @param integer $post_id Inserted post ID.
* @param object $post Inserted post object.
* @since 0.9
* @since 4.1.0 Removed `$post->post_type` variable.
*/
do_action( 'ap_processed_new_question', $post_id, $post );
}
// Update qameta terms.
ap_update_qameta_terms( $post_id );
}
/**
* Trigger posts hooks right after saving answer.
*
* @param integer $post_id Post ID.
* @param object $post Post Object
* @param boolean $updated Is updating post
* @since 4.1.0
* @since 4.1.2 Do not process if form not submitted. Insert updated to activity table.
* @since 4.1.8 Add `ap_delete_images_not_in_content`.
*/
public static function save_answer_hooks( $post_id, $post, $updated ) {
if ( wp_is_post_autosave( $post ) || wp_is_post_revision( $post ) ) {
return;
}
if ( $updated ) {
// Deleted unused images from meta.
ap_delete_images_not_in_content( $post_id );
}
$form = anspress()->get_form( 'answer' );
$values = $form->get_values();
$activity_type = ! empty( $values['post_id']['value'] ) ? 'edit_answer' : 'new_answer';
// Update parent question's answer count.
ap_update_answers_count( $post->post_parent );
$qameta = array(
'last_updated' => current_time( 'mysql' ),
'activities' => array(
'type' => $activity_type,
'user_id' => $post->post_author,
'date' => current_time( 'mysql' ),
),
);
// Check if anonymous post and have name.
if ( $form->is_submitted() && ! is_user_logged_in() && ap_allow_anonymous() && ! empty( $values['anonymous_name']['value'] ) ) {
$qameta['fields'] = array(
'anonymous_name' => $values['anonymous_name']['value'],
);
}
/**
* Modify qameta args which will be inserted after inserting
* or updating answer.
*
* @param array $qameta Qameta arguments.
* @param object $post Post object.
* @param boolean $updated Is updated.
* @since 4.1.0
*/
$qameta = apply_filters( 'ap_insert_answer_qameta', $qameta, $post, $updated );
ap_insert_qameta( $post_id, $qameta );
if ( $updated ) {
/**
* Action triggered right after updating answer.
*
* @param integer $post_id Inserted post ID.
* @param object $post Inserted post object.
* @since 0.9
* @since 4.1.0 Removed `$post->post_type` variable.
*/
do_action( 'ap_processed_update_answer' , $post_id, $post );
} else {
/**
* Action triggered right after inserting new answer.
*
* @param integer $post_id Inserted post ID.
* @param object $post Inserted post object.
* @since 0.9
* @since 4.1.0 Removed `$post->post_type` variable.
*/
do_action( 'ap_processed_new_answer', $post_id, $post );
}
// Update qameta terms.
ap_update_qameta_terms( $post_id );
}
/**
* Trigger activity update hook on question and answer status transition.
*
* @param string $new_status New post status.
* @param string $old_status Old post status.
* @param WP_Post $post WordPress post object.
* @return void
* @since 4.1.2
*/
public static function transition_post_status( $new_status, $old_status, $post ) {
if ( 'new' === $old_status || ! in_array( $post->post_type, [ 'answer', 'question' ], true ) ) {
return;
}
$question_id = 'answer' === $post->post_type ? $post->post_parent : $post->ID;
$answer_id = 'answer' === $post->post_type ? $post->ID : 0;
// Log to db.
ap_activity_add( array(
'q_id' => $question_id,
'a_id' => $answer_id,
'action' => 'status_' . $new_status,
) );
}
/**
* Update user meta of vote
*
* @param integer $userid User ID who is voting.
* @param string $type Vote type.
* @param integer $actionid Post ID.
* @param integer $receiving_userid User who is receiving vote.
*/
public static function update_user_vote_casted_count( $userid, $type, $actionid, $receiving_userid ) {
$voted = ap_count_post_votes_by( 'user_id', $userid );
// Update total casted vote of user.
update_user_meta( $userid, '__up_vote_casted', $voted['votes_up'] );
update_user_meta( $userid, '__down_vote_casted', $voted['votes_down'] );
}
/**
* Update qameta subscribers count on adding new subscriber.
*
* @param integer $rows Number of rows deleted.
* @param string $where Where clause.
*/
public static function delete_subscriber( $ref_id, $user_id, $event ) {
// Remove ids from event.
$esc_event = ap_esc_subscriber_event( $event );
if ( in_array( $esc_event, [ 'question', 'answer', 'comment' ], true ) ) {
ap_update_subscribers_count( $ref_id );
}
}
public static function display_question_metas( $metas, $question_id ) {
if ( is_user_logged_in() && is_question() && ap_is_addon_active( 'email.php' ) ) {
$metas['subscribe'] = ap_subscribe_btn( false, false );
}
return $metas;
}
/**
* Make human_time_diff strings translatable.
*
* @param string $since Time since.
* @return string
* @since 2.4.8
*
* @deprecated 4.1.13
*/
public static function human_time_diff( $since ) {
$replace = array(
'min' => __( 'minute', 'anspress-question-answer' ),
'mins' => __( 'minutes', 'anspress-question-answer' ),
'hour' => __( 'hour', 'anspress-question-answer' ),
'hours' => __( 'hours', 'anspress-question-answer' ),
'day' => __( 'day', 'anspress-question-answer' ),
'days' => __( 'days', 'anspress-question-answer' ),
'week' => __( 'week', 'anspress-question-answer' ),
'weeks' => __( 'weeks', 'anspress-question-answer' ),
'year' => __( 'year', 'anspress-question-answer' ),
'years' => __( 'years', 'anspress-question-answer' ),
);
return strtr( $since, $replace );
}
/**
* Filter recent comments widget args.
* Exclude AnsPress comments from recent commenst widget.
*
* @param array $args Comments arguments.
* @return array
*/
public static function widget_comments_args( $args ) {
$args['type__not_in'] = [ 'anspress' ];
return $args;
}
/**
* Subscribe OP to his own question.
*
* @param integer $post_id Post ID.
* @param object $_post post objct.
*
* @category haveTest
*
* @since unknown Introduced
* @since 4.1.5 Moved from addons/free/email.php
*/
public static function question_subscription( $post_id, $_post ) {
if ( $_post->post_author > 0 ) {
ap_new_subscriber( $_post->post_author, 'question', $_post->ID );
}
}
/**
* Subscribe author to their answer. Answer id is stored in event name.
*
* @param integer $post_id Post ID.
* @param object $_post Post object.
*
* @category haveTest
*
* @since unknown Introduced
* @since 4.1.5 Moved from addons/free/email.php
*/
public static function answer_subscription( $post_id, $_post ) {
if ( $_post->post_author > 0 ) {
ap_new_subscriber( $_post->post_author, 'answer_' . $post_id, $_post->post_parent );
}
}
/**
* Update qameta subscribers count on adding new subscriber.
*
* @param integer $subscriber_id id of new subscriber added.
* @param integer $user_id id of user.
* @param string $event Subscribe event.
* @param integer $ref_id Reference id.
*
* @category haveTest
*
* @since unknown
* @since 4.1.5 Update answer subscribers count.
*/
public static function new_subscriber( $subscribe_id, $user_id, $event, $ref_id ) {
// Remove ids from event.
$esc_event = ap_esc_subscriber_event( $event );
if ( in_array( $esc_event, [ 'question', 'answer', 'comment' ], true ) ) {
ap_update_subscribers_count( $ref_id );
}
// Update answer subscribers count.
if ( 'answer' === $esc_event ) {
$event_id = ap_esc_subscriber_event_id( $event );
ap_update_subscribers_count( $event_id );
}
}
/**
* Update qameta subscribers count before deleting subscribers.
*
* @param string $rows Number of rows deleted.
* @param string $where Where clause.
*
* @category haveTest
*
* @since 4.1.5
*/
public static function delete_subscribers( $rows, $where ) {
if ( ! isset( $where['subs_ref_id'] ) || ! isset( $where['subs_event'] ) ) {
return;
}
// Remove ids from event.
$esc_event = ap_esc_subscriber_event( $where['subs_event'] );
if ( in_array( $esc_event, [ 'question', 'answer', 'comment' ], true ) ) {
ap_update_subscribers_count( $where['subs_ref_id'] );
}
}
/**
* Delete subscriptions.
*
* @param integer $postid Post ID.
*
* @since unknown Introduced
* @since 4.1.5 Moved from addons/free/email.php
*/
public static function delete_subscriptions( $postid ) {
$_post = get_post( $postid );
if ( 'question' === $_post->post_type ) {
// Delete question subscriptions.
ap_delete_subscribers( array(
'subs_event' => 'question',
'subs_ref_id' => $postid,
) );
}
if ( 'answer' === $_post->post_type ) {
// Delete question subscriptions.
ap_delete_subscribers( array(
'subs_event' => 'answer_' . $_post->post_parent,
) );
}
}
/**
* Add comment subscriber.
*
* If question than subscription event will be `question_{$question_id}` and ref id will contain
* comment id. If answer than subscription event will be `answer_{$answer_id}` and ref_id
* will contain comment ID.
*
* @param object $comment Comment object.
* @since unknown Introduced
* @since 4.1.5 Moved from addons/free/email.php
* @since 4.1.8 Changed event.
*/
public static function comment_subscription( $comment ) {
if ( $comment->user_id > 0 ) {
$_post = ap_get_post( $comment->comment_post_ID );
$type = $_post->post_type . '_' . $_post->ID;
ap_new_subscriber( $comment->user_id, $type, $comment->comment_ID );
}
}
/**
* Delete comment subscriptions right before deleting comment.
*
* @param integer $comment_id Comment ID.
* @param int|WP_Comment $_comment Comment object.
*
* @since unknown Introduced
* @since 4.1.5 Moved from addons/free/email.php
* @since 4.1.8 Changed event.
*/
public static function delete_comment_subscriptions( $comment_id, $_comment ) {
$_post = get_post( $_comment->comment_post_ID );
if ( in_array( $_post->post_type, [ 'question', 'answer' ], true ) ) {
$type = $_post->post_type . '_' . $_post->ID;
$row = ap_delete_subscribers( array(
'subs_event' => $type,
'subs_ref_id' => $_comment->comment_ID,
) );
}
}
/**
* Include anspress comments count.
* This fixes no comments visible while using DIVI.
*
* @param integer $count Comments count
* @param integer $post_id Post ID.
* @return integer
*
* @since 4.1.13
*/
public static function get_comments_number( $count, $post_id ) {
global $post_type;
if ( $post_type == 'question' || ( defined( 'DOING_AJAX' ) && true === DOING_AJAX && 'ap_form_comment' === ap_isset_post_value( 'action' ) ) ) {
$get_comments = get_comments( array(
'post_id' => $post_id,
'status' => 'approve'
) );
$types = separate_comments( $get_comments );
if( ! empty( $types['anspress'] ) ) {
$count = count( $types['anspress'] );
}
}
return $count;
}
}
Expand full source code Collapse full source code View on GitHub: includes/hooks.php:20
Add your comment