/** * Builds the selection criteria from request and returns it. * * @return array */ protected function getSelectionCriteria() { /** @type TableSchema $schema */ $schema = $this->getModel()->getTableSchema(); $criteria = ['params' => []]; if (null !== ($value = $this->request->getParameter(ApiOptions::FIELDS))) { $criteria['select'] = explode(',', $value); } else { $criteria['select'] = ['*']; } if (null !== ($value = $this->request->getPayloadData(ApiOptions::PARAMS))) { $criteria['params'] = $value; } if (null !== ($value = $this->request->getParameter(ApiOptions::FILTER))) { $native = $this->convertFilterToNative($value, $criteria['params'], [], $schema->columns); $criteria['condition'] = $native['where']; if (is_array($native['params'])) { if (is_array($criteria['params'])) { $criteria['params'] = array_merge($criteria['params'], $native['params']); } else { $criteria['params'] = $native['params']; } } // Add current user ID into parameter array if in condition, but not specified. if (false !== stripos($value, ':user_id')) { if (!isset($criteria['params'][':user_id'])) { $criteria['params'][':user_id'] = SessionUtility::getCurrentUserId(); } } } $value = intval($this->request->getParameter(ApiOptions::LIMIT)); $maxAllowed = $this->getMaxRecordsReturnedLimit(); if ($value < 1 || $value > $maxAllowed) { // impose a limit to protect server $value = $maxAllowed; } $criteria['limit'] = $value; // merge in possible payload options $optionNames = [ApiOptions::OFFSET, ApiOptions::ORDER, ApiOptions::GROUP]; foreach ($optionNames as $option) { if (null !== ($value = $this->request->getParameter($option))) { $criteria[$option] = $value; } elseif (!empty($otherNames = ApiOptions::getAliases($option))) { foreach ($otherNames as $other) { if (null !== ($value = $this->request->getParameter($other))) { $criteria[$option] = $value; } elseif (null !== ($value = $this->request->getPayloadData($other))) { $criteria[$option] = $value; } } } if (!isset($criteria[$option]) && null !== ($value = $this->request->getPayloadData($option))) { $criteria[$option] = $value; } } return $criteria; }
/** * * * IMPORTANT: The representation of the data will be placed back into the original location/position in the $record * from which it was "normalized". This means that any client-side handlers will have to deal with the bogus * determinations. Just be aware. * * Below is a side-by-side comparison of record data as shown sent by or returned to the caller, and sent to an * event handler. * * REST API v1.0 Event Representation * ------------- -------------------- * Single row... Add a 'record' key and make it look like a multi-row * * array( array( * 'id' => 1, 'record' => array( * ) 0 => array( 'id' => 1, ), * ), * ), * * Multi-row... Stays the same...or gets wrapped by adding a 'record' key * * array( array( * 'record' => array( 'record' => array( * 0 => array( 'id' => 1 ), 0 => array( 'id' => 1 ), * 1 => array( 'id' => 2 ), 1 => array( 'id' => 2 ), * 2 => array( 'id' => 3 ), 2 => array( 'id' => 3 ), * ), ), * ) ) * * or... * * array( array( * 0 => array( 'id' => 1 ), 'record' => array( * 1 => array( 'id' => 2 ), 0 => array( 'id' => 1 ), * 2 => array( 'id' => 3 ), 1 => array( 'id' => 2 ), * ), 2 => array( 'id' => 3 ), * ), * ) */ protected function detectRequestMembers() { $wrapper = ResourcesWrapper::getWrapper(); // override - don't call parent class here $this->payload = $this->getPayloadData(); if (!empty($this->resource)) { if (!empty($this->resourceId)) { if (!empty($this->payload)) { // fix wrapper on posted single record if (!isset($this->payload[$wrapper])) { // single records don't use the record wrapper, so wrap it $this->payload = [$wrapper => [$this->payload]]; } } } elseif (ArrayUtils::isArrayNumeric($this->payload)) { // import from csv, etc doesn't include a wrapper, so wrap it $this->payload = [$wrapper => $this->payload]; } else { if (!empty($this->payload)) { switch ($this->request->getMethod()) { case Verbs::POST: case Verbs::PUT: case Verbs::PATCH: case Verbs::MERGE: // fix wrapper on posted single record if (!isset($this->payload[$wrapper])) { // stuff it back in for event $this->payload[$wrapper] = [$this->payload]; } break; } } } $this->options = $this->request->getParameters(); // merge in possible payload options $optionNames = [ApiOptions::LIMIT, ApiOptions::OFFSET, ApiOptions::ORDER, ApiOptions::GROUP, ApiOptions::FIELDS, ApiOptions::IDS, ApiOptions::FILTER, ApiOptions::PARAMS, ApiOptions::CONTINUES, ApiOptions::ROLLBACK]; foreach ($optionNames as $key => $value) { if (!array_key_exists($value, $this->options)) { if (array_key_exists($value, $this->payload)) { $this->options[$value] = $this->payload[$value]; } elseif (!empty($otherNames = ApiOptions::getAliases($value))) { foreach ($otherNames as $other) { if (!array_key_exists($other, $this->options)) { if (array_key_exists($other, $this->payload)) { $this->options[$value] = $this->payload[$other]; } } else { $this->options[$value] = $this->options[$other]; } } } } } // set defaults if not present if (Verbs::GET == $this->request->getMethod()) { // default for GET should be "return all fields" if (!array_key_exists(ApiOptions::FIELDS, $this->options)) { $this->options[ApiOptions::FIELDS] = '*'; } } // Add server side filtering properties $resource = $this->name . '/' . $this->resource; if (null != ($ssFilters = Session::getServiceFilters($this->getRequestedAction(), $this->parent->name, $resource))) { $this->options['ss_filters'] = $ssFilters; } } }