/**
  * List of public and user's private problems
  *
  * @param Request $r
  * @throws InvalidDatabaseOperationException
  */
 public static function apiList(Request $r)
 {
     // Authenticate request
     try {
         self::authenticateRequest($r);
     } catch (UnauthorizedException $e) {
         // Do nothing, we allow unauthenticated users to use this API
     }
     self::validateList($r);
     // Sort results
     $order = 'problem_id';
     // Order by problem_id by default.
     $sorting_options = array('title', 'submissions', 'accepted', 'ratio', 'points', 'score');
     // "order_by" may be one of the allowed options, otherwise the default ordering will be used.
     if (!is_null($r['order_by']) && in_array($r['order_by'], $sorting_options)) {
         $order = $r['order_by'];
     }
     // "mode" may be a valid one, for compatibility reasons 'descending' is the mode by default.
     if (!is_null($r['mode']) && ($r['mode'] === 'asc' || $r['mode'] === 'desc')) {
         $mode = $r['mode'];
     } else {
         $mode = 'desc';
     }
     $response = array();
     $response['results'] = array();
     $author_id = null;
     // There are basically three types of users:
     // - Non-logged in users: Anonymous
     // - Logged in users with normal permissions: Normal
     // - Logged in users with administrative rights: Admin
     $user_type = USER_ANONYMOUS;
     if (!is_null($r['current_user_id'])) {
         $author_id = intval($r['current_user_id']);
         if (Authorization::IsSystemAdmin($r['current_user_id'])) {
             $user_type = USER_ADMIN;
         } else {
             $user_type = USER_NORMAL;
         }
     }
     // Search for problems whose title has $query as a substring.
     $query = is_null($r['query']) ? null : $r['query'];
     if (!is_null($r['offset']) && !is_null($r['rowcount'])) {
         // Skips the first $offset rows of the result.
         $offset = intval($r['offset']);
         // Specifies the maximum number of rows to return.
         $rowcount = intval($r['rowcount']);
     } else {
         $offset = (is_null($r['page']) ? 0 : intval($r['page']) - 1) * PROBLEMS_PER_PAGE;
         $rowcount = PROBLEMS_PER_PAGE;
     }
     $total = 0;
     $response['results'] = ProblemsDAO::byUserType($user_type, $order, $mode, $offset, $rowcount, $query, $author_id, $r['tag'], $total);
     $response['total'] = $total;
     $response['status'] = 'ok';
     return $response;
 }