private function clean_endpoint_setting(&$setting) { if (!Utilities::is_structure($setting)) { return; } foreach ($setting as $key => &$value) { if (Utilities::is_structure($value)) { $this->clean_endpoint_setting($value); } else { $do_unset = false; if (is_null($value)) { $do_unset = true; } // skip params containing unmerged vars; allows for optional params if (!$this->is_merged($value)) { $do_unset = true; } if ($do_unset) { if (is_array($setting)) { unset($setting[$key]); } else { unset($setting->key); } } } } }
public function go($endpoint_name, $endpoint_vars = array(), $local_vars = array()) { if (is_array($local_vars)) { $this->local_vars = $local_vars; } // must set endpoint name before checking for bypass_prerequisites $this->config->custom_endpoint_name = $endpoint_name; $this->config->set_actual_endpoint_name(); $this->config->apply_custom_endpoint_params(); if (empty($this->config->settings->endpoints->{$this->config->custom_endpoint_name}->bypass_prerequisites)) { $this->process_prerequisites(); } // must set endpoint name after processing prerequisites to setup requested endpoint $this->config->custom_endpoint_name = $endpoint_name; $this->config->set_actual_endpoint_name(); $this->config->apply_custom_endpoint_params(); if (empty($this->config->settings->endpoints->{$this->config->actual_endpoint_name})) { throw new SDKlessException("specified endpoint does not exist in config: {$this->config->actual_endpoint_name}"); } if (is_array($endpoint_vars)) { $this->endpoint_vars = $endpoint_vars; } else { $this->endpoint_vars = array(); } if (!empty($this->endpoint_vars['array_set'])) { $this->config->apply_endpoint_array_set_vars($this->endpoint_vars['array_set']); } $this->config->apply_endpoint_vars($this->endpoint_vars); $this->config->set_method(); $this->auth->setup_oauth_header($this->global_vars); $this->time_limit = array_key_exists('time_limit', $this->local_vars) ? $this->local_vars['time_limit'] : $this->config->get_endpoint_setting('time_limit'); $output = array(); $total_count = 0; // loop for paging while (true) { $response = $this->response->get($this->config, $this->time_limit); if (empty($response)) { break; } $response_count = $this->output->populate($this->config, $response, $output); if ($response_count == 0) { break; } $total_count += $response_count; // if total count >= limit, truncate/break $limit = $this->config->get_endpoint_setting('limit'); if (!empty($limit) && $total_count >= $limit) { if (is_array($output)) { $output = array_slice($output, 0, $limit); } break; } // if paging, setup next page param $paging = $this->config->get_endpoint_setting('paging'); if (empty($paging->parameters)) { break; } $paging_type = empty($paging->type) ? "page_number" : $paging->type; $endpoint_params = $this->config->get_endpoint_setting('parameters'); $page_size_param = empty($paging->parameters->page_size->name) ? "page_size" : $paging->parameters->page_size->name; $page_size = empty($endpoint_params->{$page_size_param}) ? null : $endpoint_params->{$page_size_param}; $paging_base = isset($paging->parameters->{$paging_type}->base) ? $paging->parameters->{$paging_type}->base : 1; switch ($paging_type) { case 'page_number': if (empty($paging->parameters->{$paging_type}->name)) { throw new SDKlessException("paging {$paging_type} name required"); } $paging_counter_param = $paging->parameters->{$paging_type}->name; if (!isset($paging_counter)) { $paging_counter = $paging_base; } $paging_counter++; $keys = array('parameters', $paging_counter_param); $this->config->set_endpoint_setting($keys, $paging_counter); // response count is less than page size; break if (!empty($page_size) && $response_count < $page_size) { break 2; } break; case 'record_offset': if (empty($paging->parameters->{$paging_type}->name)) { throw new SDKlessException("paging {$paging_type} name required"); } $paging_counter_param = $paging->parameters->{$paging_type}->name; if (!isset($paging_counter)) { $paging_counter = $paging_base; } if (empty($page_size)) { throw new SDKlessException("endpoint page size parameter required for offset paging"); } $paging_counter += $page_size; $keys = array('parameters', $paging_counter_param); $this->config->set_endpoint_setting($keys, $paging_counter); // response count is less than page size; break if (!empty($page_size) && $response_count < $page_size) { break 2; } break; case 'cursor': if (empty($paging->parameters->{$paging_type}->location) || !is_array($paging->parameters->{$paging_type}->location)) { throw new SDKlessException("paging {$paging_type} location array required"); } $data = json_decode(json_encode($response)); // make copy of response (can't be output; may no longer contain paging info) foreach ($paging->parameters->{$paging_type}->location as $location_key) { $data = Utilities::get_by_key($data, $location_key); } if (empty($data)) { break 2; } $this->config->set_endpoint_setting('uri', $data); break; } } $output_config = $this->config->get_endpoint_setting('output'); // filter output if (Utilities::is_structure($output) && !empty($output_config->filter)) { $unfiltered_output = json_decode(json_encode($output)); $output = array(); if (!Utilities::is_structure($output_config->filter)) { throw new SDKlessException("config endpoint output filter must be a structure"); } foreach ($output_config->filter as $filter) { $match_found = false; if (empty($filter->search_key) || !isset($filter->search_value)) { throw new SDKlessException("search_key and search_value are required for output filtering"); } foreach ($unfiltered_output as $item) { $item_value = Utilities::get_by_key($item, $filter->search_key); if (is_null($item_value)) { continue; } if ($item_value == $filter->search_value) { $match_found = true; if (!empty($filter->return_key)) { $return_key = $filter->return_key; return Utilities::get_by_key($item, $return_key); } $output[] = $item; } } if (!empty($filter->return_type)) { switch ($filter->return_type) { case 'boolean': return $match_found; break; case '!boolean': return !$match_found; break; } } } } $this->config->reset_to_unmerged(); return $output; }
private function set_item_by_search($data, $location_item, $location_key, &$output_item) { if (!Utilities::is_structure($data)) { throw new SDKlessException("output data item must be a structure when config location item is a structure"); } if (empty($location_item->search_key) || !isset($location_item->search_value) || !isset($location_item->return_key)) { throw new SDKlessException("search_key, search_value, and return_key are required when location item is a structure"); } $search_key = $location_item->search_key; $return_key = $location_item->return_key; foreach ($data as $child_item) { // if location item is a structure, data must be a structure if (!Utilities::is_structure($child_item)) { throw new SDKlessException("output data item must be a structure when config location item is a structure"); } if (isset($child_item->{$search_key}) && $child_item->{$search_key} == $location_item->search_value) { $output_item[$location_key] = $child_item->{$return_key}; } } }
private function get_curl_opts() { $request_options = $this->config->get_endpoint_setting('request_options'); $opts = array('CURLOPT_RETURNTRANSFER' => true, 'CURLOPT_FOLLOWLOCATION' => true); if (!empty($this->time_limit)) { $opts['CURLOPT_CONNECTTIMEOUT'] = $this->time_limit; $opts['CURLOPT_TIMEOUT'] = $this->time_limit; } if (!empty($request_options)) { foreach ($request_options as $key => $value) { switch ($key) { case 'headers': $headers = array(); foreach ($value as $header_key => $header_value) { $headers[] = "{$header_key}: {$header_value}"; } $opts['CURLOPT_HTTPHEADER'] = $headers; break; default: $opts["CURLOPT_{$key}"] = $value; } } } if ($this->config->method == 'post') { $opts['CURLOPT_POST'] = true; $params = $this->config->get_endpoint_setting('parameters'); if (empty($params)) { $opts['CURLOPT_POSTFIELDS'] = ''; } else { $input_format = $this->config->get_endpoint_setting('input_format'); switch ($input_format) { case 'json': $params = json_encode($params); break; case 'query_string': $params = http_build_query($params); break; default: // multi-level structures will cause uncatchable error in curl_setopt foreach ($params as $param) { if (Utilities::is_structure($param)) { throw new SDKlessException("multi-level structure endpoint parameters must be encoded"); } } } $opts['CURLOPT_POSTFIELDS'] = $params; } } return $opts; }