admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce(self::NONCE), 'i18n' => array( 'saving' => __('Saving…', 'ai-eshop-optimizer'), 'saved' => __('Saved.', 'ai-eshop-optimizer'), 'error' => __('Something went wrong.', 'ai-eshop-optimizer'), 'needQ' => __('Please enter a question.', 'ai-eshop-optimizer'), 'rename' => __('Rename group', 'ai-eshop-optimizer'), 'delGroup' => __('Delete this group? Its FAQs become ungrouped (the entries are kept).', 'ai-eshop-optimizer'), 'delFaq' => __('Delete this FAQ entry permanently?', 'ai-eshop-optimizer'), ), )); } public function render_subtab() { $groups = get_terms(array( 'taxonomy' => self::TAXONOMY, 'hide_empty' => false, 'orderby' => 'name', )); if (is_wp_error($groups)) { $groups = array(); } $faqs = get_posts(array( 'post_type' => self::POST_TYPE, 'post_status' => array('publish', 'draft', 'pending'), 'numberposts' => -1, 'orderby' => array('menu_order' => 'ASC', 'date' => 'ASC'), )); $by_group = array(); foreach ($faqs as $f) { $terms = get_the_terms($f->ID, self::TAXONOMY); $gid = (!is_wp_error($terms) && !empty($terms)) ? (int) $terms[0]->term_id : 0; $by_group[$gid][] = $f; } $sections = array(); foreach ($groups as $g) { $sections[] = array( 'id' => (int) $g->term_id, 'name' => $g->name, 'faqs' => isset($by_group[(int) $g->term_id]) ? $by_group[(int) $g->term_id] : array(), ); } $sections[] = array( 'id' => 0, 'name' => __('Ungrouped', 'ai-eshop-optimizer'), 'faqs' => isset($by_group[0]) ? $by_group[0] : array(), ); $this->render_template('faq.php', array( 'groups' => $groups, 'sections' => $sections, )); } private function guard() { if (!check_ajax_referer(self::NONCE, 'nonce', false)) { wp_send_json_error(array('message' => __('Security check failed.', 'ai-eshop-optimizer'))); } $cap = defined('AIEO_CAPABILITY') ? AIEO_CAPABILITY : 'manage_woocommerce'; if (!current_user_can($cap)) { wp_send_json_error(array('message' => __('You are not allowed to do this.', 'ai-eshop-optimizer'))); } } public function ajax_create() { $this->guard(); $question = isset($_POST['question']) ? sanitize_text_field(wp_unslash($_POST['question'])) : ''; $answer = isset($_POST['answer']) ? wp_kses_post(wp_unslash($_POST['answer'])) : ''; $group_id = isset($_POST['group_id']) ? (int) $_POST['group_id'] : 0; if ('' === $question) { wp_send_json_error(array('message' => __('Please enter a question.', 'ai-eshop-optimizer'))); } $top = get_posts(array( 'post_type' => self::POST_TYPE, 'post_status' => 'any', 'numberposts' => 1, 'orderby' => 'menu_order', 'order' => 'DESC', 'fields' => 'ids', )); $max = !empty($top) ? (int) get_post_field('menu_order', $top[0]) : 0; $pid = wp_insert_post(array( 'post_type' => self::POST_TYPE, 'post_title' => $question, 'post_content' => $answer, 'post_status' => 'publish', 'menu_order' => $max + 1, ), true); if (is_wp_error($pid)) { wp_send_json_error(array('message' => $pid->get_error_message())); } if ($group_id > 0) { wp_set_post_terms($pid, array($group_id), self::TAXONOMY, false); } wp_send_json_success(array('post_id' => $pid)); } public function ajax_update_q() { $this->guard(); $pid = isset($_POST['post_id']) ? (int) $_POST['post_id'] : 0; $q = isset($_POST['question']) ? sanitize_text_field(wp_unslash($_POST['question'])) : ''; if ($pid <= 0 || self::POST_TYPE !== get_post_type($pid)) { wp_send_json_error(array('message' => __('Unknown FAQ.', 'ai-eshop-optimizer'))); } if ('' === $q) { wp_send_json_error(array('message' => __('Please enter a question.', 'ai-eshop-optimizer'))); } wp_update_post(array('ID' => $pid, 'post_title' => $q)); wp_send_json_success(array('post_id' => $pid)); } public function ajax_delete() { $this->guard(); $pid = isset($_POST['post_id']) ? (int) $_POST['post_id'] : 0; if ($pid <= 0 || self::POST_TYPE !== get_post_type($pid)) { wp_send_json_error(array('message' => __('Unknown FAQ.', 'ai-eshop-optimizer'))); } wp_trash_post($pid); wp_send_json_success(array('post_id' => $pid)); } public function ajax_reorder() { $this->guard(); $raw = isset($_POST['order']) ? wp_unslash((string) $_POST['order']) : ''; $rows = '' !== $raw ? json_decode($raw, true) : null; if (!is_array($rows)) { wp_send_json_error(array('message' => __('Invalid payload.', 'ai-eshop-optimizer'))); } foreach ($rows as $r) { if (!is_array($r)) { continue; } $pid = isset($r['post_id']) ? (int) $r['post_id'] : 0; $gid = isset($r['group_id']) ? (int) $r['group_id'] : 0; $ord = isset($r['menu_order']) ? (int) $r['menu_order'] : 0; if ($pid <= 0 || self::POST_TYPE !== get_post_type($pid)) { continue; } wp_update_post(array('ID' => $pid, 'menu_order' => $ord)); wp_set_post_terms($pid, $gid > 0 ? array($gid) : array(), self::TAXONOMY, false); } wp_send_json_success(array('message' => __('Order saved.', 'ai-eshop-optimizer'))); } public function ajax_add_group() { $this->guard(); $name = isset($_POST['name']) ? sanitize_text_field(wp_unslash($_POST['name'])) : ''; if ('' === $name) { wp_send_json_error(array('message' => __('Please enter a group name.', 'ai-eshop-optimizer'))); } $res = wp_insert_term($name, self::TAXONOMY); if (is_wp_error($res)) { wp_send_json_error(array('message' => $res->get_error_message())); } wp_send_json_success(array('term_id' => (int) $res['term_id'])); } public function ajax_rename_group() { $this->guard(); $gid = isset($_POST['group_id']) ? (int) $_POST['group_id'] : 0; $name = isset($_POST['name']) ? sanitize_text_field(wp_unslash($_POST['name'])) : ''; if ($gid <= 0 || '' === $name) { wp_send_json_error(array('message' => __('Invalid group.', 'ai-eshop-optimizer'))); } $res = wp_update_term($gid, self::TAXONOMY, array('name' => $name)); if (is_wp_error($res)) { wp_send_json_error(array('message' => $res->get_error_message())); } wp_send_json_success(array('term_id' => $gid)); } public function ajax_delete_group() { $this->guard(); $gid = isset($_POST['group_id']) ? (int) $_POST['group_id'] : 0; if ($gid <= 0) { wp_send_json_error(array('message' => __('Invalid group.', 'ai-eshop-optimizer'))); } wp_delete_term($gid, self::TAXONOMY); wp_send_json_success(array('term_id' => $gid)); } }