Current File : /home/pacjaorg/public_html/copwordpres/wp-content/plugins/betterdocs/includes/Core/FAQBuilder.php |
<?php
namespace WPDeveloper\BetterDocs\Core;
use WP_Query;
use WP_Error;
use WPDeveloper\BetterDocs\Utils\Base;
class FAQBuilder extends Base {
/**
* REST API namespace
* @var string
*/
private $namespace = 'betterdocs';
public $post_type = 'betterdocs_faq';
public $category = 'betterdocs_faq_category';
/**
*
* Initialize the class and start calling our hooks and filters
*
* @since 1.0.0
*
*/
public function __construct() {
// assign default admin capabilities for docs, doc terms, doc tags, knowledge base
add_action( 'init', [$this, 'register_post'] );
// fires after a new betterdocs_faq_category is created
add_action( 'created_betterdocs_faq_category', [$this, 'action_created_betterdocs_faq_category'], 10, 2 );
add_action( 'rest_api_init', [$this, 'register_api_endpoint'] );
add_action('rest_betterdocs_faq_category_query', array($this, 'faq_category_orderby_meta'), 10, 2);
// Enqueue Scripts
add_action( 'admin_enqueue_scripts', [$this, 'enqueue'] );
}
public function enqueue( $hook ) {
if ( $hook === 'betterdocs_page_betterdocs-faq' ) {
betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/css/faq.css' );
betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/js/faq.js' );
// removing emoji support
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
betterdocs()->assets->localize( 'betterdocs-admin-faq', 'betterdocs', [
'dir_url' => BETTERDOCS_ABSURL,
'rest_url' => esc_url_raw( rest_url() ),
'free_version' => betterdocs()->version,
'nonce' => wp_create_nonce( 'wp_rest' )
] );
}
}
public function output() {
betterdocs()->views->get( 'admin/faq-builder' );
}
/**
*
* Register post type and taxonomies
*
* @since 1.0.0
*
*/
public function register_post() {
/**
* Register category taxonomy
*/
$category_labels = [
'name' => __( 'FAQ Categories', 'betterdocs' ),
'singular_name' => __( 'FAQ Category', 'betterdocs' ),
'all_items' => __( 'FAQ Categories', 'betterdocs' ),
'parent_item' => __( 'Parent FAQ Category', 'betterdocs' ),
'parent_item_colon' => __( 'Parent FAQ Category:', 'betterdocs' ),
'edit_item' => __( 'Edit Category', 'betterdocs' ),
'update_item' => __( 'Update Category', 'betterdocs' ),
'add_new_item' => __( 'Add New FAQ Category', 'betterdocs' ),
'new_item_name' => __( 'New FAQ Category Name', 'betterdocs' ),
'menu_name' => __( 'Categories', 'betterdocs' )
];
$category_args = [
'hierarchical' => true,
'public' => false,
'labels' => $category_labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'show_in_rest' => true,
'has_archive' => false,
'rewrite' => false,
'capabilities' => [
'manage_terms' => 'manage_doc_terms',
'edit_terms' => 'edit_doc_terms',
'delete_terms' => 'delete_doc_terms',
'assign_terms' => 'edit_docs'
]
];
register_taxonomy( $this->category, [$this->post_type], $category_args );
register_term_meta( $this->category, 'order', ['show_in_rest' => true] );
register_term_meta( $this->category, 'status', ['show_in_rest' => true] );
register_term_meta( $this->category, '_betterdocs_faq_order', ['show_in_rest' => true] );
/**
* Register post type
*/
$labels = [
'name' => __( 'BetterDocs FAQ', 'betterdocs' ),
'singular_name' => __( 'BetterDocs FAQ', 'betterdocs' ),
'menu_name' => __( 'FAQ', 'betterdocs' ),
'name_admin_bar' => __( 'FAQ', 'betterdocs' ),
'add_new' => __( 'Add New', 'betterdocs' ),
'add_new_item' => __( 'Add New FAQ', 'betterdocs' ),
'new_item' => __( 'New FAQ', 'betterdocs' ),
'edit_item' => __( 'Edit FAQ', 'betterdocs' ),
'view_item' => __( 'View FAQ', 'betterdocs' ),
'all_items' => __( 'All FAQ', 'betterdocs' ),
'search_items' => __( 'Search FAQ', 'betterdocs' ),
'parent_item_colorn' => null,
'not_found' => __( 'No FAQ found', 'betterdocs' ),
'not_found_in_trash' => __( 'No FAQ found in trash', 'betterdocs' )
];
$args = [
'labels' => $labels,
'description' => __( 'Add new faq from here', 'betterdocs' ),
'public' => false,
'public_queryable' => true,
'exclude_from_search' => false,
'show_ui' => true,
'show_in_menu' => false,
'query_var' => true,
'capability_type' => ['doc', 'docs'],
'hierarchical' => true,
'map_meta_cap' => true,
'has_archive' => false,
'rewrite' => false,
'show_in_rest' => true,
'menu_icon' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg' ),
'supports' => ['title', 'editor', 'thumbnail', 'excerpt', 'author', 'revisions', 'custom-fields', 'comments']
];
register_post_type( $this->post_type, $args );
}
/**
* Default the taxonomy's terms' order if it's not set.
*
* @param string $tax_slug The taxonomy's slug.
*/
public function action_created_betterdocs_faq_category( $term_id ) {
$order = $this->get_max_taxonomy_order( 'betterdocs_faq_category' );
update_term_meta( $term_id, 'order', $order++ );
update_term_meta( $term_id, 'status', 1 );
}
/**
* Default the taxonomy's terms' order if it's not set.
*
* @param string $tax_slug The taxonomy's slug.
*/
public function default_term_order( $tax_slug ) {
$terms = get_terms( $tax_slug, ['hide_empty' => false] );
$order = $this->get_max_taxonomy_order( $tax_slug );
foreach ( $terms as $term ) {
if ( ! get_term_meta( $term->term_id, 'order', true ) ) {
update_term_meta( $term->term_id, 'order', $order );
$order++;
}
}
}
/**
* Get the maximum order for this taxonomy. This will be applied to terms that don't have a tax position.
*/
private function get_max_taxonomy_order( $tax_slug ) {
global $wpdb;
$max_term_order = $wpdb->get_col(
$wpdb->prepare(
"SELECT MAX( CAST( tm.meta_value AS UNSIGNED ) )
FROM $wpdb->terms t
JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id AND tt.taxonomy = '%s'
JOIN $wpdb->termmeta tm ON tm.term_id = t.term_id WHERE tm.meta_key = 'order'",
$tax_slug
)
);
$max_term_order = is_array( $max_term_order ) ? current( $max_term_order ) : 0;
return (int) $max_term_order === 0 || empty( $max_term_order ) ? 1 : (int) $max_term_order + 1;
}
/**
* Re-Order the taxonomies based on the order value.
*
* @param array $pieces Array of SQL query clauses.
* @param array $taxonomies Array of taxonomy names.
* @param array $args Array of term query args.
*/
public function set_tax_order( $pieces, $taxonomies, $args ) {
foreach ( $taxonomies as $taxonomy ) {
global $wpdb;
if ( $taxonomy === 'betterdocs_faq_category' ) {
$join_statement = " LEFT JOIN $wpdb->termmeta AS term_meta ON t.term_id = term_meta.term_id AND term_meta.meta_key = 'order'";
if ( ! $this->does_substring_exist( $pieces['join'], $join_statement ) ) {
$pieces['join'] .= $join_statement;
}
$pieces['orderby'] = 'ORDER BY CAST( term_meta.meta_value AS UNSIGNED )';
}
}
return $pieces;
}
/**
* Order the taxonomies on the front end.
*/
public function front_end_order_terms() {
if ( ! is_admin() ) {
add_filter( 'terms_clauses', [$this, 'set_tax_order'], 10, 3 );
}
}
/**
* Check if a substring exists inside a string.
*
* @param string $string The main string (haystack) we're searching in.
* @param string $substring The substring we're searching for.
*
* @return bool True if substring exists, else false.
*/
protected function does_substring_exist( $string, $substring ) {
return strstr( $string, $substring ) !== false;
}
public function register_api_endpoint() {
register_rest_route( $this->namespace, '/faq/sample_data', [
'methods' => ['POST'],
'callback' => [$this, 'create_faq_sample'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/posts/(?P<type>\S+)', [
'methods' => ['GET'],
'callback' => [$this, 'fetch_faq_posts'],
'permission_callback' => '__return_true'
] );
register_rest_route( $this->namespace, '/faq/create_category', [
'methods' => ['POST'],
'callback' => [$this, 'create_faq_category'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/update_category', [
'methods' => ['POST'],
'callback' => [$this, 'update_faq_category'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/delete_category', [
'methods' => ['POST'],
'callback' => [$this, 'delete_faq_category'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/create_post', [
'methods' => ['POST'],
'callback' => [$this, 'create_betterdocs_faq'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/update_post', [
'methods' => ['POST'],
'callback' => [$this, 'update_betterdocs_faq'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/delete_post', [
'methods' => ['POST'],
'callback' => [$this, 'delete_betterdocs_faq'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/category_status', [
'methods' => ['POST'],
'callback' => [$this, 'update_category_status'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/category_order', [
'methods' => ['POST'],
'callback' => [$this, 'update_faq_category_order'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/update_order_by_category', [
'methods' => ['POST'],
'callback' => [$this, 'update_faq_order_by_category'],
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
] );
register_rest_route( $this->namespace, '/faq/uncategorised', [
'methods' => ['GET'],
'callback' => [$this, 'get_uncategorised_faq'],
'permission_callback' => '__return_true'
] );
register_rest_route( $this->namespace, '/faq/category_search', [
'methods' => ['GET'],
'callback' => [$this, 'category_search'],
'permission_callback' => '__return_true',
'args' => array(
'title' => array(
'type' => 'string',
'required' => true
),
),
] );
}
public function create_faq_sample( $params ) {
$sample_data = json_decode( $params->get_param( 'sample_data' ), true );
foreach ( $sample_data as $key => $value ) {
$insert_term = wp_insert_term(
$key,
'betterdocs_faq_category'
);
if ( $insert_term ) {
foreach ( $value['posts'] as $key => $value ) {
$this->insert_betterdocs_faq( $value['post_title'], $value['post_content'], $insert_term['term_id'] );
}
}
}
return true;
}
public function create_faq_category( $params ) {
$title = $params->get_param( 'title' );
$description = $params->get_param( 'description' );
$description = ( $description !== 'undefined' ) ? $description : '';
$slug = $params->get_param( 'slug' );
return $this->insert_betterdocs_faq_category( $title, $description, $slug );
}
public function update_faq_category( $params ) {
$term_id = $params->get_param( 'term_id' );
$title = $params->get_param( 'title' );
$description = $params->get_param( 'description' );
$description = ( $description !== 'undefined' ) ? $description : '';
$slug = $params->get_param( 'slug' );
$update = wp_update_term( $term_id, 'betterdocs_faq_category', [
'name' => $title,
'slug' => $slug,
'description' => $description
] );
if ( is_wp_error( $update ) ) {
return $update;
} else {
return true;
}
}
public function delete_faq_category( $params ) {
$term_id = $params->get_param( 'term_id' );
$delete = wp_delete_term( $term_id, 'betterdocs_faq_category' );
if ( is_wp_error( $delete ) ) {
return $delete;
} else {
return true;
}
}
public function insert_betterdocs_faq_category( $title, $description, $slug = '' ) {
$insert_term = wp_insert_term(
$title,
'betterdocs_faq_category',
[
'slug' => $slug,
'description' => $description
]
);
if ( is_wp_error( $insert_term ) ) {
return $insert_term;
} else {
return true;
}
}
public function update_faq_category_order( $params ) {
$faq_category_order = $params->get_param( 'faq_category_order' );
$faq_category_order = json_decode( $faq_category_order, true );
foreach ( $faq_category_order as $order_data ) {
if ( (int) $order_data['current_position'] != (int) $order_data['updated_position'] ) {
update_term_meta( $order_data['id'], 'order', ( (int) $order_data['updated_position'] ) );
}
}
return true;
}
public function insert_betterdocs_faq( $post_title, $post_content, $term_id ) {
$post = wp_insert_post(
[
'post_type' => 'betterdocs_faq',
'post_title' => wp_strip_all_tags( $post_title ),
'post_content' => $post_content,
'post_status' => 'publish'
]
);
if ( $term_id ) {
$set_terms = wp_set_object_terms( $post, $term_id, 'betterdocs_faq_category' );
if ( is_wp_error( $set_terms ) ) {
return $set_terms;
} else {
return $this->update_faq_order_on_insert( $term_id, $post );
}
} else {
return $post;
}
}
public function update_faq_order_on_insert( $term_id, $post ) {
$term_meta = get_term_meta( $term_id, '_betterdocs_faq_order' );
if ( ! empty( $term_meta ) ) {
$term_meta_arr = explode( ",", $term_meta[0] );
if ( ! in_array( $post, $term_meta_arr ) ) {
array_unshift( $term_meta_arr, $post );
$docs_ordering_data = filter_var_array( wp_unslash( $term_meta_arr ), FILTER_SANITIZE_NUMBER_INT );
return update_term_meta( $term_id, '_betterdocs_faq_order', implode( ',', $docs_ordering_data ) );
}
} else {
return update_term_meta( $term_id, '_betterdocs_faq_order', $post );
}
}
/**
* Update _betterdocs_faq_order meta when new post created
*/
public function update_faq_order_by_category( $params ) {
$term_id = $params->get_param( 'term_id' );
$posts = $params->get_param( 'posts' );
return update_term_meta( $term_id, '_betterdocs_faq_order', $posts );
}
public function create_betterdocs_faq( $params ) {
$post_title = $params->get_param( 'post_title' );
$post_content = $params->get_param( 'post_content' );
$term_id = $params->get_param( 'term_id' );
return $this->insert_betterdocs_faq( $post_title, $post_content, $term_id );
}
public function update_betterdocs_faq( $params ) {
$post_id = $params->get_param( 'post_id' );
$post_title = $params->get_param( 'post_title' );
$post_content = $params->get_param( 'post_content' );
$status = $params->get_param( 'status' );
$term_id = $params->get_param( 'term_id' );
if ( $status ) {
$data = [
'post_type' => 'betterdocs_faq',
'ID' => $post_id,
'status' => $status
];
} else {
$data = [
'post_type' => 'betterdocs_faq',
'ID' => $post_id,
'post_title' => $post_title,
'post_content' => $post_content
];
if ( $term_id ) {
$data['tax_input'] = [
"betterdocs_faq_category" => $term_id
];
$term_meta = get_term_meta( $term_id, '_betterdocs_faq_order' );
$term_meta_arr = explode( ",", $term_meta[0] );
if ( ! in_array( $post_id, $term_meta_arr ) ) {
array_unshift( $term_meta_arr, $post_id );
$docs_ordering_data = filter_var_array( wp_unslash( $term_meta_arr ), FILTER_SANITIZE_NUMBER_INT );
update_term_meta( $term_id, '_betterdocs_faq_order', implode( ',', $docs_ordering_data ) );
}
}
}
return wp_update_post( $data );
}
public function delete_betterdocs_faq( $params ) {
$post_id = $params->get_param( 'post_id' );
return wp_delete_post( $post_id );
}
public function faq_post_loop( $args ) {
$posts = [];
$query = new WP_Query( $args );
if ( $query->have_posts() ):
while ( $query->have_posts() ): $query->the_post();
$posts[get_the_ID()]['title'] = get_the_title();
$posts[get_the_ID()]['content'] = get_the_content();
endwhile;
endif;
return $posts;
}
public function update_category_status( $params ) {
$term_id = $params->get_param( 'term_id' );
$status = $params->get_param( 'status' );
return update_term_meta( $term_id, 'status', $status );
}
public function fetch_faq_posts( $params ) {
$faq = [];
$type = $params->get_param( 'type' );
if ( $type == 'category' ) {
$taxonomy_objects = get_terms( 'betterdocs_faq_category', [
'hide_empty' => false
] );
if ( $taxonomy_objects && ! is_wp_error( $taxonomy_objects ) ):
foreach ( $taxonomy_objects as $term ):
$args = [
'post_type' => 'betterdocs_faq',
'post_status' => 'publish',
'post_per_page' => -1,
'tax_query' => [
[
'taxonomy' => 'betterdocs_faq_category',
'field' => 'term_id',
'terms' => $term->term_id
]
]
];
$posts = $this->faq_post_loop( $args );
$faq[$term->slug] = [
(array) $term,
'posts' => $posts
];
endforeach;
endif;
} else {
$args = [
'post_type' => 'betterdocs_faq',
'post_status' => 'publish',
'post_per_page' => -1
];
$posts = $this->faq_post_loop( $args );
$faq['posts'] = $posts;
}
return $faq;
}
public function get_uncategorised_faq() {
$available_terms = array_map( function ( $term ) {
return $term->term_id;
}, get_terms( [
'taxonomy' => 'betterdocs_faq_category',
'hide_empty' => false
] ) );
return get_posts( [
'post_type' => 'betterdocs_faq',
'post_status' => ['publish', 'draft'],
'posts_per_page' => -1,
'tax_query' => [
'relation' => 'AND',
[
'taxonomy' => 'betterdocs_faq_category',
'field' => 'term_id',
'terms' => $available_terms,
'operator' => 'NOT IN'
]
]
] );
}
public function category_search( $request ) {
$title = $request['title'];
// Perform the taxonomy search
$taxonomy_args = array(
'name__like' => $title,
'taxonomy' => 'betterdocs_faq_category',
'hide_empty' => false
);
$taxonomies = get_terms($taxonomy_args);
if (!empty($taxonomies)) {
$result = array();
foreach ($taxonomies as $taxonomy) {
$result[] = array(
'id' => $taxonomy->term_id,
'count' => $taxonomy->count,
'description' => $taxonomy->description,
'name' => $taxonomy->name,
'slug' => $taxonomy->slug
// Add more fields as needed
);
}
// Return the taxonomy data
return $result;
} else {
// Taxonomy not found
return new WP_Error('taxonomy_not_found', 'Taxonomy not found.', array('status' => 404));
}
}
public function faq_category_orderby_meta($args, $request) {
if ($args['taxonomy'] === 'betterdocs_faq_category') {
$args['orderby'] = 'meta_value_num';
$args['meta_key'] = 'order';
}
return $args;
}
}