743 lines
19 KiB
PHP
743 lines
19 KiB
PHP
<?php
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
use WP_Rocket\Engine\License\API\User;
|
|
|
|
/**
|
|
* Results Controller class.
|
|
*
|
|
* Handles API calls related to Survey Results
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @package UserFeedback
|
|
* @author David Paternina
|
|
*/
|
|
class UserFeedback_Results {
|
|
|
|
public function __construct() {
|
|
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
|
|
}
|
|
|
|
/**
|
|
* Registers REST routes
|
|
*
|
|
* @return void
|
|
*/
|
|
public function register_routes() {
|
|
register_rest_route(
|
|
'userfeedback/v1',
|
|
'/results-summary',
|
|
array(
|
|
'methods' => 'GET',
|
|
'callback' => array( $this, 'get_results_summary' ),
|
|
'permission_callback' => array( $this, 'view_results_permission_check' ),
|
|
'args' => array(
|
|
'orderby' => array(
|
|
'type' => 'string',
|
|
'sanitize_callback' => array( $this, 'sanitize_orderby_param' ),
|
|
),
|
|
'order' => array(
|
|
'type' => 'string',
|
|
'sanitize_callback' => array( $this, 'sanitize_order_param' ),
|
|
),
|
|
),
|
|
)
|
|
);
|
|
|
|
register_rest_route(
|
|
'userfeedback/v1',
|
|
'/surveys/(?P<id>\w+)/results',
|
|
array(
|
|
'methods' => 'GET',
|
|
'callback' => array( $this, 'get_survey_results' ),
|
|
'permission_callback' => array( $this, 'view_results_permission_check' ),
|
|
)
|
|
);
|
|
|
|
register_rest_route(
|
|
'userfeedback/v1',
|
|
'/surveys/(?P<id>\w+)/responses',
|
|
array(
|
|
'methods' => 'GET',
|
|
'callback' => array( $this, 'get_survey_responses' ),
|
|
'permission_callback' => array( $this, 'view_results_permission_check' ),
|
|
'args' => array(
|
|
'filter' => array(
|
|
'type' => 'object',
|
|
'sanitize_callback' => array( $this, 'sanitize_filter_param' ),
|
|
),
|
|
'per_page' => array(
|
|
'type' => 'integer',
|
|
'sanitize_callback' => 'absint',
|
|
),
|
|
'page' => array(
|
|
'type' => 'integer',
|
|
'sanitize_callback' => 'absint',
|
|
),
|
|
),
|
|
)
|
|
);
|
|
|
|
register_rest_route(
|
|
'userfeedback/v1',
|
|
'/surveys/(?P<id>\w+)/responses/trash',
|
|
array(
|
|
'methods' => 'POST',
|
|
'callback' => array( $this, 'trash_responses' ),
|
|
'permission_callback' => array( $this, 'view_results_permission_check' ),
|
|
'args' => array(
|
|
'response_ids' => array(
|
|
'required' => true,
|
|
'type' => 'array',
|
|
'description' => __('Survey response ids.', 'userfeedback-lite'),
|
|
'sanitize_callback' => function($ids) {
|
|
return array_map('esc_attr', $ids);
|
|
},
|
|
'validate_callback' => array( $this, 'validate_response_ids' )
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
register_rest_route(
|
|
'userfeedback/v1',
|
|
'/surveys/(?P<id>\w+)/responses/restore',
|
|
array(
|
|
'methods' => 'POST',
|
|
'callback' => array( $this, 'restore_responses' ),
|
|
'permission_callback' => array( $this, 'view_results_permission_check' ),
|
|
'args' => array(
|
|
'response_ids' => array(
|
|
'required' => true,
|
|
'type' => 'array',
|
|
'description' => __('Survey response ids.', 'userfeedback-lite'),
|
|
'sanitize_callback' => function($ids) {
|
|
return array_map('esc_attr', $ids);
|
|
},
|
|
'validate_callback' => array( $this, 'validate_response_ids' )
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
register_rest_route(
|
|
'userfeedback/v1',
|
|
'/surveys/(?P<id>\w+)/responses',
|
|
array(
|
|
'methods' => 'DELETE',
|
|
'callback' => array( $this, 'delete_responses' ),
|
|
'permission_callback' => array( $this, 'view_results_permission_check' ),
|
|
'args' => array(
|
|
'response_ids' => array(
|
|
'required' => true,
|
|
'type' => 'array',
|
|
'description' => __('Survey response ids.', 'userfeedback-lite'),
|
|
'sanitize_callback' => function($ids) {
|
|
return array_map('esc_attr', $ids);
|
|
},
|
|
'validate_callback' => array( $this, 'validate_response_ids' )
|
|
)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get Survey results data
|
|
*
|
|
* @param $survey_id
|
|
* @return mixed|null
|
|
*/
|
|
public static function get_survey_results_data( $survey_id, $from_date = '', $to_date = '' ) {
|
|
$start_date_7_days = ( new DateTime() )->modify( '-7 days' );
|
|
$start_date_30_days = ( new DateTime() )->modify( '-30 days' );
|
|
$end_date = new DateTime();
|
|
|
|
$survey_query = UserFeedback_Survey::where(
|
|
array(
|
|
'id' => $survey_id
|
|
)
|
|
)->select( array( 'title', 'status', 'impressions', 'questions', 'type' ) );
|
|
|
|
$survey = $survey_query->single();
|
|
|
|
if ( 'nps' === $survey->type ) {
|
|
$where_conditions = array( 'survey_id' => $survey_id );
|
|
|
|
// By default, nps will return last 30 days results including today
|
|
if ( empty( $from_date ) && empty( $to_date ) ) {
|
|
$today = new DateTime();
|
|
$todayFormatted = $today->format('Y-m-d');
|
|
|
|
$dateBefore30Days = new DateTime();
|
|
$dateBefore30Days->modify('-30 days');
|
|
$dateBefore30DaysFormatted = $dateBefore30Days->format('Y-m-d');
|
|
|
|
$from_date = $dateBefore30DaysFormatted;
|
|
$to_date = $todayFormatted;
|
|
}
|
|
|
|
if ( ! empty( $from_date ) ) {
|
|
$where_conditions[] = array(
|
|
'DATE(submitted_at)',
|
|
'>=',
|
|
$from_date,
|
|
);
|
|
}
|
|
|
|
if ( ! empty( $to_date ) ) {
|
|
$where_conditions[] = array(
|
|
'DATE(submitted_at)',
|
|
'<=',
|
|
$to_date,
|
|
);
|
|
}
|
|
|
|
$responses = UserFeedback_Response::where( $where_conditions )
|
|
->select( array( 'id', 'survey_id', 'answers', 'submitted_at', 'status' ) )
|
|
->get();
|
|
|
|
$survey->nps_overview = self::get_nps_survey_overview( $responses );
|
|
$survey->responses = $responses;
|
|
} else {
|
|
$survey = $survey_query->with_count_where(
|
|
'responses',
|
|
array(
|
|
array(
|
|
'submitted_at',
|
|
'>=',
|
|
$start_date_7_days->format( 'Y-m-d' ),
|
|
),
|
|
array(
|
|
'submitted_at',
|
|
'<=',
|
|
$end_date->format( 'Y-m-d' ),
|
|
),
|
|
),
|
|
'responses_count_7_days'
|
|
)
|
|
->with_count_where(
|
|
'responses',
|
|
array(
|
|
array(
|
|
'submitted_at',
|
|
'>=',
|
|
$start_date_30_days->format( 'Y-m-d' ),
|
|
),
|
|
array(
|
|
'submitted_at',
|
|
'<=',
|
|
$end_date->format( 'Y-m-d' ),
|
|
),
|
|
),
|
|
'responses_count_30_days'
|
|
)
|
|
->with( array( 'responses' ) )
|
|
->single();
|
|
}
|
|
|
|
if ( $survey === null ) {
|
|
return null;
|
|
}
|
|
|
|
// Survey total responses
|
|
$total_responses = sizeof( $survey->responses );
|
|
$survey->responses_count = $total_responses;
|
|
|
|
// Survey question stats
|
|
$quantitative_question_types = array( 'radio-button', 'image-radio', 'icon-choice', 'checkbox', 'nps', 'star-rating' );
|
|
$question_stats = array();
|
|
|
|
$questions = $survey->questions;
|
|
$responses = $survey->responses;
|
|
|
|
foreach ( $questions as $question ) {
|
|
$id = $question->id;
|
|
$type = $question->type;
|
|
|
|
$is_quantitative = in_array( $type, $quantitative_question_types );
|
|
|
|
$question_data = array(
|
|
'id' => $question->id,
|
|
'title' => $question->title,
|
|
'type' => $question->type,
|
|
'total_answers' => 0,
|
|
'skipped' => 0,
|
|
'is_quantitative' => $is_quantitative,
|
|
);
|
|
|
|
if ( $is_quantitative ) {
|
|
switch ( $type ) {
|
|
case 'radio-button':
|
|
case 'image-radio':
|
|
case 'icon-choice':
|
|
case 'checkbox':
|
|
$question_data['options'] = array_map(
|
|
function ( $option ) {
|
|
return array(
|
|
'value' => $option,
|
|
'count' => 0,
|
|
);
|
|
},
|
|
$question->config->options
|
|
);
|
|
break;
|
|
case 'nps':
|
|
$question_data['options'] = array_map(
|
|
function ( $option ) {
|
|
return array(
|
|
'value' => $option,
|
|
'count' => 0,
|
|
);
|
|
},
|
|
array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 )
|
|
);
|
|
break;
|
|
case 'star-rating':
|
|
$question_data['options'] = array_map(
|
|
function ( $option ) {
|
|
return array(
|
|
'value' => $option,
|
|
'count' => 0,
|
|
);
|
|
},
|
|
array( 1, 2, 3, 4, 5 )
|
|
);
|
|
break;
|
|
}
|
|
} else {
|
|
$question_data['answers'] = array();
|
|
}
|
|
|
|
foreach ( $responses as $response ) {
|
|
$question_answer_index = array_search( $id, array_column( $response->answers, 'question_id' ) );
|
|
$value = $response->answers[ $question_answer_index ]->value;
|
|
$extra = isset( $response->answers[ $question_answer_index ]->extra ) ? $response->answers[ $question_answer_index ]->extra : null;
|
|
|
|
if ( $question_answer_index === false || $value === null ) {
|
|
$question_data['skipped']++;
|
|
continue;
|
|
} else {
|
|
$question_data['total_answers']++;
|
|
}
|
|
|
|
if ( $is_quantitative ) {
|
|
if ( is_array( $value ) ) {
|
|
foreach ( $value as $picked_value ) {
|
|
$option_index = array_search( $picked_value, array_column( $question_data['options'], 'value' ) );
|
|
$question_data['options'][ $option_index ]['count']++;
|
|
}
|
|
} else {
|
|
if ( in_array( $type, array( 'icon-choice', 'image-radio' ), true ) ) {
|
|
$question_options = array_map(function($option) {
|
|
return $option['value']->label;
|
|
}, $question_data['options']);
|
|
} else {
|
|
$question_options = array_column( $question_data['options'], 'value' );
|
|
}
|
|
|
|
$option_index = array_search( $value, $question_options );
|
|
$question_data['options'][ $option_index ]['count']++;
|
|
}
|
|
}
|
|
|
|
$question_data['answers'][] = array(
|
|
'response_id' => $response->id,
|
|
'value' => $value,
|
|
'date' => $response->submitted_at,
|
|
'extra' => $extra,
|
|
);
|
|
}
|
|
|
|
$question_stats[] = $question_data;
|
|
}
|
|
|
|
$survey->question_stats = $question_stats;
|
|
return $survey;
|
|
}
|
|
|
|
private static function get_nps_survey_overview( $responses = array() )
|
|
{
|
|
$totalCount = count($responses);
|
|
|
|
if ($totalCount > 0) {
|
|
$detractors = 0;
|
|
$passives = 0;
|
|
$promoters = 0;
|
|
|
|
foreach ($responses as $item) {
|
|
if (!isset($item->answers[0]->value)) {
|
|
continue;
|
|
}
|
|
|
|
$value = $item->answers[0]->value;
|
|
|
|
if ($value >= 1 && $value <= 6) {
|
|
$detractors++;
|
|
} elseif ($value >= 7 && $value <= 8) {
|
|
$passives++;
|
|
} elseif ($value >= 9 && $value <= 10) {
|
|
$promoters++;
|
|
}
|
|
}
|
|
|
|
// Calculate percentages and round to 2 decimal places
|
|
$detractorsPercentage = floor(($detractors / $totalCount) * 100);
|
|
$passivesPercentage = floor(($passives / $totalCount) * 100);
|
|
$promotersPercentage = floor(($promoters / $totalCount) * 100);
|
|
|
|
return array(
|
|
'detractor' => $detractorsPercentage,
|
|
'passive' => $passivesPercentage,
|
|
'promoter' => $promotersPercentage,
|
|
'nps' => floor($promotersPercentage - $detractorsPercentage),
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'detractor' => 0,
|
|
'passive' => 0,
|
|
'promoter' => 0,
|
|
'nps' => 'N/A',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Permissions/capabilities check
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function view_results_permission_check() {
|
|
return current_user_can( 'userfeedback_view_results' );
|
|
}
|
|
|
|
/**
|
|
* Sanitize filter parameter to prevent SQL injection
|
|
*
|
|
* @param mixed $filters The filter parameter value
|
|
* @return array Sanitized filters with only allowed keys
|
|
*/
|
|
public function sanitize_filter_param( $filters ) {
|
|
if ( ! is_array( $filters ) ) {
|
|
return array();
|
|
}
|
|
|
|
$allowed_filter_attrs = array( 'status' );
|
|
$sanitized = array();
|
|
|
|
foreach ( $filters as $key => $value ) {
|
|
// Only allow whitelisted column names
|
|
$sanitized_key = sanitize_key( $key );
|
|
if ( in_array( $sanitized_key, $allowed_filter_attrs, true ) ) {
|
|
$sanitized[ $sanitized_key ] = sanitize_text_field( $value );
|
|
}
|
|
}
|
|
|
|
return $sanitized;
|
|
}
|
|
|
|
/**
|
|
* Sanitize orderby parameter to prevent SQL injection
|
|
*
|
|
* @param string $orderby
|
|
* @return string
|
|
*/
|
|
public function sanitize_orderby_param( $orderby ) {
|
|
// Allowed columns for survey queries
|
|
$allowed_orderby = array( 'id', 'title', 'status', 'type', 'impressions', 'publish_at', 'created_at' );
|
|
|
|
$orderby = sanitize_key( $orderby );
|
|
|
|
return in_array( $orderby, $allowed_orderby, true ) ? $orderby : 'created_at';
|
|
}
|
|
|
|
/**
|
|
* Sanitize order parameter
|
|
*
|
|
* @param string $order
|
|
* @return string
|
|
*/
|
|
public function sanitize_order_param( $order ) {
|
|
$order = strtolower( sanitize_key( $order ) );
|
|
return in_array( $order, array( 'asc', 'desc' ), true ) ? $order : 'desc';
|
|
}
|
|
|
|
/**
|
|
* Validate response ids callback
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function validate_response_ids($ids) {
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'userfeedback_survey_responses';
|
|
$placeholders = implode( ', ', array_fill( 0, count( $ids ), '%d' ) );
|
|
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is hardcoded safe prefix + known table name.
|
|
$query = $wpdb->prepare( "SELECT * FROM {$table_name} WHERE id IN ({$placeholders})", ...$ids );
|
|
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Prepared via $wpdb->prepare() above; direct query required for IN() validation.
|
|
$result = $wpdb->get_results( $query ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
|
|
return count($result) === count($ids);
|
|
}
|
|
|
|
/**
|
|
* Get Results summary by date range
|
|
*
|
|
* @param WP_REST_Request $request
|
|
* @return WP_REST_Response
|
|
* @throws Exception
|
|
*/
|
|
public function get_results_summary( WP_REST_Request $request ) {
|
|
$start_date = $request->get_param( 'start_date' );
|
|
$end_date = $request->get_param( 'end_date' );
|
|
$survey_id = $request->get_param( 'survey_id' );
|
|
$orderby = $request->get_param( 'orderby' );
|
|
$order = $request->get_param( 'order' );
|
|
|
|
$orderby = empty( $orderby ) ? 'created_at' : $orderby;
|
|
$order = empty( $order ) ? 'desc' : $order;
|
|
|
|
$start_date = $start_date ? new DateTime( $start_date ) : ( new DateTime() )->modify( '-7 days' )->setTime( 0, 0 );
|
|
|
|
if ( ! userfeedback_is_pro_version() || ! userfeedback_is_licensed() ) {
|
|
$start_date = ( new DateTime() )->modify( '-7 days' )->setTime( 0, 0 );
|
|
}
|
|
|
|
$end_date = $end_date ? new DateTime( $end_date ) : new DateTime();
|
|
$end_date = $end_date->modify( '+1 day' );
|
|
|
|
$where_config = array(
|
|
array(
|
|
'submitted_at',
|
|
'>=',
|
|
$start_date->format( 'Y-m-d' ),
|
|
),
|
|
array(
|
|
'submitted_at',
|
|
'<=',
|
|
$end_date->format( 'Y-m-d' ),
|
|
),
|
|
);
|
|
|
|
if ( isset( $survey_id ) ) {
|
|
$where_config[] = array(
|
|
'survey_id',
|
|
'=',
|
|
$survey_id,
|
|
);
|
|
}
|
|
|
|
$responses_query_obj = UserFeedback_Response::query();
|
|
/**
|
|
* Get responses
|
|
*/
|
|
$responses = UserFeedback_Response::where( $where_config )
|
|
->select(
|
|
array(
|
|
"{$responses_query_obj->get_table()}.id",
|
|
"{$responses_query_obj->get_table()}.survey_id",
|
|
"{$responses_query_obj->get_table()}.submitted_at",
|
|
)
|
|
)
|
|
->get();
|
|
|
|
/*
|
|
* Get data for graph
|
|
*/
|
|
$data_points = array();
|
|
|
|
$iterate_date = $start_date;
|
|
while ( $iterate_date->diff( $end_date )->days > 0 ) {
|
|
$responses_for_date = array_filter(
|
|
$responses,
|
|
function( $response ) use ( $iterate_date ) {
|
|
$response_date = new DateTime( $response->submitted_at );
|
|
return $iterate_date->format( 'Y-m-d' ) === $response_date->format( 'Y-m-d' );
|
|
}
|
|
);
|
|
|
|
$data_points[] = array(
|
|
'date' => $iterate_date->format( 'Y-m-d' ),
|
|
'count' => sizeof( $responses_for_date ),
|
|
);
|
|
|
|
$iterate_date->modify( '+1 day' );
|
|
}
|
|
|
|
/*
|
|
* Get Surveys info
|
|
*/
|
|
$surveys_query = UserFeedback_Survey::where(
|
|
array(
|
|
array( 'status', '!=', 'trash' ),
|
|
)
|
|
);
|
|
|
|
$surveys_query->select( array( 'title', 'type', 'status', 'created_at' ) )
|
|
->with_count( array( 'responses' ) )
|
|
->with_count_where( 'responses', $where_config, 'range_responses_count' )
|
|
->sort( $orderby, $order );
|
|
|
|
return new WP_REST_Response(
|
|
array(
|
|
'total_responses' => sizeof( $responses ),
|
|
'data_points' => $data_points,
|
|
'surveys' => $surveys_query->get(),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get Survey with responses
|
|
*
|
|
* @param WP_REST_Request $request
|
|
* @return WP_REST_Response
|
|
*/
|
|
public function get_survey_results( WP_REST_Request $request ) {
|
|
$survey_id = $request['id'];
|
|
$from_date = $request['from'];
|
|
$to_date = $request['to'];
|
|
|
|
$survey = self::get_survey_results_data( $survey_id, $from_date, $to_date );
|
|
|
|
if ( $survey === null ) {
|
|
return new WP_REST_Response( null, 404 );
|
|
}
|
|
|
|
// Remove the original questions and responses arrays to get a cleaner AJAX response
|
|
unset( $survey->questions );
|
|
unset( $survey->responses );
|
|
|
|
return new WP_REST_Response( $survey );
|
|
}
|
|
|
|
/**
|
|
* Get Survey responses
|
|
*
|
|
* @param WP_REST_Request $request
|
|
* @return WP_REST_Response
|
|
*/
|
|
public function get_survey_responses( WP_REST_Request $request ) {
|
|
|
|
(new UserFeedback_Response)->add_status_column();
|
|
|
|
$survey_id = $request->get_param( 'id' );
|
|
|
|
// Get responses
|
|
$query = UserFeedback_Response::where(
|
|
array(
|
|
'survey_id' => $survey_id,
|
|
array( 'status', '!=', 'trash' ), // Get only published and drafts by default
|
|
)
|
|
)
|
|
->sort( 'id', 'desc' )
|
|
->paginate(
|
|
$request->get_param( 'per_page' ),
|
|
$request->get_param( 'page' )
|
|
);
|
|
|
|
if ( $request->has_param( 'filter' ) ) {
|
|
$filters = $request->get_param( 'filter' );
|
|
|
|
// Sanitization callback should have already cleaned this
|
|
if ( ! is_array( $filters ) ) {
|
|
$filters = array();
|
|
}
|
|
|
|
foreach ( $filters as $attr => $value ) {
|
|
if ( $value === 'all' ) {
|
|
$query->add_where(
|
|
array(
|
|
array('status', '!=', 'trash'),
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
|
|
// Only 'status' should reach here due to sanitization
|
|
$query->add_where(
|
|
array(
|
|
array( $attr, '=', $value ),
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
$responses = $query->get();
|
|
|
|
// Data for quick filters
|
|
$count_by_status_result = UserFeedback_Response::query()
|
|
->select( array( 'status', 'count' ) )
|
|
->where( array( 'survey_id' => $survey_id ) )
|
|
->group_by( 'status' )
|
|
->get();
|
|
|
|
$allTotal = 0;
|
|
|
|
foreach ( $count_by_status_result as $item ) {
|
|
if ( $item->status !== 'trash' ) {
|
|
$allTotal += $item->count;
|
|
}
|
|
|
|
if ( $item->status === 'publish' ) {
|
|
$item->status = 'publish';
|
|
}
|
|
}
|
|
|
|
array_unshift(
|
|
$count_by_status_result,
|
|
array(
|
|
'status' => 'all',
|
|
'count' => $allTotal,
|
|
)
|
|
);
|
|
|
|
$responses['status_filters'] = $count_by_status_result;
|
|
|
|
return new WP_REST_Response( $responses );
|
|
}
|
|
|
|
|
|
/**
|
|
* Trash responses
|
|
*
|
|
* @param WP_REST_Request $request
|
|
* @return WP_REST_Response
|
|
*/
|
|
public function trash_responses( WP_REST_Request $request ) {
|
|
$response_ids = $request->get_param( 'response_ids' );
|
|
// Trash responses
|
|
$responses = UserFeedback_Response::trash($response_ids);
|
|
return new WP_REST_Response( $responses );
|
|
}
|
|
|
|
/**
|
|
* Restore responses
|
|
*
|
|
* @param WP_REST_Request $request
|
|
* @return WP_REST_Response
|
|
*/
|
|
public function restore_responses( WP_REST_Request $request ) {
|
|
$response_ids = $request->get_param( 'response_ids' );
|
|
// Restore responses
|
|
$responses = UserFeedback_Response::restore($response_ids);
|
|
return new WP_REST_Response( $responses );
|
|
}
|
|
|
|
/**
|
|
* Delete responses by Id
|
|
*
|
|
* @return WP_REST_Response
|
|
*/
|
|
public function delete_responses( $data ) {
|
|
$response_ids = $data['response_ids'];
|
|
// Delete responses
|
|
UserFeedback_Response::delete($response_ids);
|
|
return new WP_REST_Response( null, 204 );
|
|
}
|
|
}
|
|
|
|
new UserFeedback_Results();
|