namespace, '/' . $this->base, array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array($this, 'get_statistic_by_user_id'), 'permission_callback' => array($this, 'check_permission'), 'args' => array( 'user_id' => array( 'validate_callback' => function ($param, $request, $key) { return is_numeric($param); } ), ), ) ) ); register_rest_route( $this->namespace, '/' . $this->base . '/(?P[\d]+)/statistic', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array($this, 'get_statistic_by_statistic_id'), 'permission_callback' => array($this, 'check_permission'), 'args' => array( 'statistic_id' => array( 'validate_callback' => function ($param, $request, $key) { return is_numeric($param); } ), ), ) ) ); } public function get_statistic_by_user_id($request) { // 1) Pre-parameter filter: allow callers to mutate incoming params before validation $params = apply_filters('acadlix_pre_get_statistic_by_user_id_params', $request->get_params(), $request); $res = []; $user_id = $params['user_id'] ?? $request->get_param('user_id'); $search = $params['search'] ?? $request->get_param('search') ?? ''; $category_ids = $params['category_ids'] ?? $request->get_param('category_ids') ?? []; // Validate required fields if (empty($user_id)) { return new WP_Error( 'missing_id', __('User id is required.', 'acadlix'), ['status' => 400] ); } // 2) Payload/Data Filter: normalize paging and other values before execution $payload = apply_filters('acadlix_get_statistic_by_user_id_payload', [ 'user_id' => intval($user_id), 'search' => (string) $search, 'category_ids' => is_array($category_ids) ? $category_ids : [$category_ids], 'page' => max(0, intval($params['page'] ?? 0)), 'pageSize' => max(1, intval($params['pageSize'] ?? 10)), ], $params); $skip = $payload['page'] * $payload['pageSize']; $res['categories'] = acadlix()->model()->category()->all(); $stat_ref = acadlix()->model()->statisticRef() ->with('quiz') ->where('user_id', $payload['user_id']) ->when(!empty($payload['category_ids']), function ($query) use ($payload) { $query->whereHas('quiz.quiz_categories', function ($q) use ($payload) { $q->whereIn('term_id', $payload['category_ids']); }); }) ->when(!empty($payload['search']), function ($query) use ($payload) { $query->whereHas('quiz', function ($q) use ($payload) { $q->where('post_title', 'like', '%' . $payload['search'] . '%'); }); }) ->orderBy("id", "desc"); $res['total'] = $stat_ref->count(); $res['stat_refs'] = $stat_ref->skip($skip)->take($payload['pageSize'])->get(); // 3) Lifecycle Action: expose retrieval to listeners do_action('acadlix_get_statistic_by_user_id', $res, $stat_ref, $payload, $params); // 4) Outbound Response Filter: allow other modules to modify the REST response $res = apply_filters('acadlix_get_statistic_by_user_id_response', $res, $stat_ref, $payload, $params); return rest_ensure_response($res); } public function get_statistic_by_statistic_id($request) { // 1) Pre-parameter filter: allow callers to mutate incoming params before validation $params = apply_filters('acadlix_pre_get_statistic_by_statistic_id_params', $request->get_params(), $request); $res = []; $statistic_id = $params['statistic_id'] ?? $request['statistic_id'] ?? $request->get_param('statistic_id'); $user_id = $params['user_id'] ?? $request->get_param('user_id'); // Validate required fields if (empty($user_id)) { return new WP_Error( 'missing_id', __('User id is required.', 'acadlix'), ['status' => 400] ); } // Validate required fields if (empty($statistic_id)) { return new WP_Error( 'missing_id', __('Statistic id is required.', 'acadlix'), ['status' => 400] ); } // 2) Payload/Data Filter: normalize values before core execution $payload = apply_filters('acadlix_get_statistic_by_statistic_id_payload', [ 'statistic_id' => intval($statistic_id), 'user_id' => intval($user_id), ], $params); $stat_ref = acadlix()->model()->statisticRef()->find($payload['statistic_id']); $appends = apply_filters('acadlix_get_statistic_by_statistic_id_quiz_appends', [ 'rendered_post_content', 'rendered_metas', 'category', 'languages', 'rendered_questions', ], $stat_ref, $payload, $params); $res['quiz'] = $stat_ref ? acadlix()->model()->quiz()->ofQuiz()->find($stat_ref->quiz_id)->setAppends($appends) : null; $res['statistic_ref'] = $stat_ref; $res['statistic'] = $stat_ref ? $stat_ref->statistics()->with("question")->get() : []; // 3) Lifecycle Action: expose retrieval to listeners do_action('acadlix_get_statistic_by_statistic_id', $res, $stat_ref, $payload, $params); // 4) Outbound Response Filter: allow response modification $res = apply_filters('acadlix_get_statistic_by_statistic_id_response', $res, $stat_ref, $payload, $params); return rest_ensure_response($res); } public function check_permission($request) { if (!is_user_logged_in()) { return new WP_Error('not_logged_in', 'Login required', ['status' => 401]); } $user_id = absint($request->get_param('user_id') ?? 0); if ($user_id && get_current_user_id() !== $user_id) { return new WP_Error('forbidden', 'Access denied', ['status' => 403]); } return true; } }