/** * Parse query string into parameters, validating and filling in defaults */ public static function parseQueryParams($queryString, $action, $singleObject) { // Handle multiple identical parameters in the CGI-standard way instead of // PHP's foo[]=bar way $getParams = Zotero_URL::proper_parse_str($queryString); $queryParams = array(); foreach (self::getDefaultQueryParams() as $key => $val) { // Don't overwrite field if already derived from another field if (!empty($queryParams[$key])) { continue; } if ($key == 'limit') { $val = self::getDefaultLimit(isset($getParams['format']) ? $getParams['format'] : ""); } // Fill defaults $queryParams[$key] = $val; // If no parameter passed, used default if (!isset($getParams[$key])) { continue; } // Some formats need special parameter handling if (isset($getParams['format'])) { if ($getParams['format'] == 'bib') { switch ($key) { // Invalid parameters case 'order': case 'sort': case 'start': case 'limit': throw new Exception("'{$key}' is not valid for format=bib", Z_ERROR_INVALID_INPUT); } } else { if ($getParams['format'] == 'keys') { switch ($key) { // Invalid parameters case 'start': throw new Exception("'{$key}' is not valid for format=bib", Z_ERROR_INVALID_INPUT); } } } } switch ($key) { case 'format': $format = $getParams[$key]; $isExportFormat = in_array($format, Zotero_Translate::$exportFormats); // All actions other than items must be Atom if ($action != 'items') { if ($format != 'atom') { throw new Exception("Invalid 'format' value '{$format}'", Z_ERROR_INVALID_INPUT); } } else { if ($isExportFormat || $format == 'csljson') { if ($singleObject || !empty($getParams['itemKey'])) { break; } $limitMax = self::getLimitMax($format); if (empty($getParams['limit'])) { throw new Exception("'limit' is required for format={$format}", Z_ERROR_INVALID_INPUT); } else { if ($getParams['limit'] > $limitMax) { throw new Exception("'limit' cannot be greater than {$limitMax} for format={$format}", Z_ERROR_INVALID_INPUT); } } } else { switch ($format) { case 'atom': case 'bib': break; default: if ($format == 'keys' && !$singleObject) { break; } throw new Exception("Invalid 'format' value '{$format}' for request", Z_ERROR_INVALID_INPUT); } } } break; case 'start': $queryParams[$key] = (int) $getParams[$key]; continue 2; case 'limit': // Maximum limit depends on 'format' $limitMax = self::getLimitMax(isset($getParams['format']) ? $getParams['format'] : ""); // If there's a maximum, enforce it if ($limitMax && (int) $getParams[$key] > $limitMax) { $getParams[$key] = $limitMax; } else { if ((int) $getParams[$key] == 0) { continue 2; } } $queryParams[$key] = (int) $getParams[$key]; continue 2; case 'content': if (isset($getParams['format']) && $getParams['format'] != 'atom') { throw new Exception("'content' is valid only for format=atom", Z_ERROR_INVALID_INPUT); } $getParams[$key] = array_values(array_unique(explode(',', $getParams[$key]))); sort($getParams[$key]); foreach ($getParams[$key] as $value) { switch ($value) { case 'none': case 'full': if (sizeOf($getParams[$key]) > 1) { throw new Exception("content={$value} is not valid in " . "multi-format responses", Z_ERROR_INVALID_INPUT); } break; case 'html': case 'citation': case 'bib': case 'json': case 'csljson': break; default: if (in_array($value, Zotero_Translate::$exportFormats)) { break; } throw new Exception("Invalid 'content' value '{$value}'", Z_ERROR_INVALID_INPUT); } } break; case 'order': // Whether to sort empty values first $queryParams['emptyFirst'] = Zotero_API::getSortEmptyFirst($getParams[$key]); switch ($getParams[$key]) { // Valid fields to sort by // // Allow all fields available in client case 'title': case 'creator': case 'itemType': case 'date': case 'publisher': case 'publicationTitle': case 'journalAbbreviation': case 'language': case 'accessDate': case 'libraryCatalog': case 'callNumber': case 'rights': case 'dateAdded': case 'dateModified': //case 'numChildren': //case 'numChildren': case 'addedBy': case 'numItems': case 'serverDateModified': // numItems is valid only for tags requests switch ($getParams[$key]) { case 'numItems': if ($action != 'tags') { throw new Exception("Invalid 'order' value '" . $getParams[$key] . "'", Z_ERROR_INVALID_INPUT); } break; } if (!isset($getParams['sort'])) { $queryParams['sort'] = self::getDefaultSort($getParams[$key]); } else { if (!in_array($getParams['sort'], array('asc', 'desc'))) { throw new Exception("Invalid 'sort' value '" . $getParams['sort'] . "'", Z_ERROR_INVALID_INPUT); } else { $queryParams['sort'] = $getParams['sort']; } } break; default: throw new Exception("Invalid 'order' value '" . $getParams[$key] . "'", Z_ERROR_INVALID_INPUT); } break; case 'sort': if (!in_array($getParams['sort'], array('asc', 'desc'))) { throw new Exception("Invalid 'sort' value '" . $getParams[$key] . "'", Z_ERROR_INVALID_INPUT); } break; } $queryParams[$key] = $getParams[$key]; } return $queryParams; }