/**
  * {@inheritdoc}
  */
 public function getNextRequest(ClientInterface $client, JobConfig $jobConfig, $response, $data)
 {
     $nextUrl = Utils::getDataFromPath($this->urlParam, $response, '.');
     if (empty($nextUrl)) {
         return false;
     }
     // since validation - cannot be greater than now
     $now = new \DateTime();
     $sinceDateTime = \DateTime::createFromFormat('U', Url::fromString($nextUrl)->getQuery()->get('since'));
     if ($sinceDateTime && $sinceDateTime > $now) {
         return false;
     }
     $config = $jobConfig->getConfig();
     if (!$this->includeParams) {
         $config['params'] = [];
     }
     if (!$this->paramIsQuery) {
         $config['endpoint'] = $nextUrl;
     } else {
         // Create an array from the query string
         $responseQuery = Query::fromString(ltrim($nextUrl, '?'))->toArray();
         $config['params'] = array_replace($config['params'], $responseQuery);
     }
     return $client->createRequest($config);
 }
 /**
  * {@inheritdoc}
  */
 public function getNextRequest(ClientInterface $client, JobConfig $jobConfig, $response, $data)
 {
     $nextUrl = Utils::getDataFromPath($this->urlParam, $response, '.');
     if (empty($nextUrl)) {
         return false;
     }
     // start_time validation
     // https://developer.zendesk.com/rest_api/docs/core/incremental_export#incremental-ticket-export
     $now = new \DateTime();
     $startDateTime = \DateTime::createFromFormat('U', Url::fromString($nextUrl)->getQuery()->get('start_time'));
     if ($startDateTime && $startDateTime > $now->modify(sprintf("-%d minutes", self::NEXT_PAGE_FILTER_MINUTES))) {
         return false;
     }
     $config = $jobConfig->getConfig();
     if (!$this->includeParams) {
         $config['params'] = [];
     }
     if (!$this->paramIsQuery) {
         $config['endpoint'] = $nextUrl;
     } else {
         // Create an array from the query string
         $responseQuery = Query::fromString(ltrim($nextUrl, '?'))->toArray();
         $config['params'] = array_replace($config['params'], $responseQuery);
     }
     return $client->createRequest($config);
 }
 /**
  * @param $response
  * @param JobConfig $jobConfig
  * @return array
  */
 public function process($response, JobConfig $jobConfig)
 {
     $config = $jobConfig->getConfig();
     if (!isset($config['parser']['method'])) {
         return $response;
     }
     $path = empty($config['dataField']) ? "." : $config['dataField'];
     if ($config['parser']['method'] == 'facebook.insights') {
         return $this->flatten($path, $response);
     }
     return $response;
 }
 /**
  * Try to find the data array within $response.
  *
  * @param array|object $response
  * @param array $config
  * @return array
  * @todo support array of dataFields
  *     - would return object with results, changing the class' API
  *     - parse would just have to loop through if it returns an object
  *     - and append $type with the dataField
  * @deprecated Use response module
  */
 public function process($response, JobConfig $jobConfig)
 {
     $config = $jobConfig->getConfig();
     // If dataField doesn't say where the data is in a response, try to find it!
     if (!empty($config['dataField'])) {
         if (is_array($config['dataField'])) {
             if (empty($config['dataField']['path'])) {
                 throw new UserException("'dataField.path' must be set!");
             }
             $path = $config['dataField']['path'];
         } elseif (is_scalar($config['dataField'])) {
             $path = $config['dataField'];
         } else {
             throw new UserException("'dataField' must be either a path string or an object with 'path' attribute.");
         }
         $data = Utils::getDataFromPath($path, $response, ".");
         if (empty($data)) {
             Logger::log('warning', "dataField '{$path}' contains no data!");
             $data = [];
         } elseif (!is_array($data)) {
             // In case of a single object being returned
             $data = [$data];
         }
     } elseif (is_array($response)) {
         // Simplest case, the response is just the dataset
         $data = $response;
     } elseif (is_object($response)) {
         // Find arrays in the response
         $arrays = [];
         foreach ($response as $key => $value) {
             if (is_array($value)) {
                 $arrays[$key] = $value;
             }
             // TODO else {$this->metadata[$key] = json_encode($value);} ? return [$data,$metadata];
         }
         $arrayNames = array_keys($arrays);
         if (count($arrays) == 1) {
             $data = $arrays[$arrayNames[0]];
         } elseif (count($arrays) == 0) {
             Logger::log('warning', "No data array found in response! (endpoint: {$config['endpoint']})", ['response' => json_encode($response)]);
             $data = [];
         } else {
             $e = new UserException("More than one array found in response! Use 'dataField' parameter to specify a key to the data array. (endpoint: {$config['endpoint']}, arrays in response root: " . join(", ", $arrayNames) . ")");
             $e->setData(['response' => json_encode($response), 'arrays found' => $arrayNames]);
             throw $e;
         }
     } else {
         $e = new UserException('Unknown response from API.');
         $e->setData(['response' => json_encode($response)]);
         throw $e;
     }
     return $data;
 }
 /**
  * @return array
  */
 public function process($response, JobConfig $jobConfig)
 {
     if (empty($jobConfig->getConfig()['parseObject'])) {
         return $response;
     }
     $config = $jobConfig->getConfig()['parseObject'];
     if (!is_object($response)) {
         if (empty($response)) {
             return [];
         }
         throw new UserException("Data in response is not an object, while one was expected!");
     }
     $path = empty($config['path']) ? "." : $config['path'];
     $key = empty($config['keyColumn']) ? "rowId" : $config['keyColumn'];
     return $this->convertObjectWithKeys(Utils::getDataFromPath($path, $response, '.'), $key);
 }
 /**
  * @expectedException \Keboola\Juicer\Exception\UserException
  * @expectedExceptionMessage More than one array found in response! Use 'dataField' parameter to specify a key to the data array. (endpoint: a, arrays in response root: results, otherArray)
  */
 public function testMultipleArraysException()
 {
     $cfg = JobConfig::create(['endpoint' => 'a']);
     $module = new FindResponseArray();
     $response = (object) ['results' => [(object) ['id' => 1], (object) ['id' => 2]], 'otherArray' => ['a', 'b']];
     $data = $module->process($response, $cfg);
 }
Example #7
0
 public function testMissingData()
 {
     $jobConfig = JobConfig::create(['endpoint' => 'ep', 'responseFilter' => 'out.arr[].in']);
     $filter = Filter::create($jobConfig);
     $data = [(object) ['id' => 1, 'out' => (object) ['arr' => [(object) ['in' => 'string'], (object) ['uh' => 'no "in" here!'], (object) ['in' => ['str', 'ing']]]]]];
     self::assertEquals([(object) ['id' => 1, 'out' => (object) ['arr' => [(object) ['in' => 'string'], (object) ['uh' => 'no "in" here!'], (object) ['in' => '["str","ing"]']]]]], $filter->run($data));
 }
Example #8
0
 /**
  * {@inheritdoc}
  */
 public function getNextRequest(ClientInterface $client, JobConfig $jobConfig, $response, $data)
 {
     if (empty($data)) {
         $this->reset();
         return false;
     } else {
         $cursor = 0;
         foreach ($data as $item) {
             $cursorVal = Utils::getDataFromPath($this->idKey, $item, '.');
             if (is_null($this->max) || $cursorVal > $this->max) {
                 $this->max = $cursorVal;
             }
             if (is_null($this->min) || $cursorVal < $this->min) {
                 $this->min = $cursorVal;
             }
             $cursor = $this->reverse ? $this->min : $this->max;
         }
         if (0 !== $this->increment) {
             if (!is_numeric($cursor)) {
                 throw new UserException("Trying to increment a pointer that is not numeric.");
             }
             $cursor += $this->increment;
         }
         $jobConfig->setParam($this->param, $cursor);
         return $client->createRequest($jobConfig->getConfig());
     }
 }
Example #9
0
 /**
  * @param JobConfig $jobConfig
  * @return ScrollerInterface
  */
 public function getScrollerForJob(JobConfig $jobConfig)
 {
     if (empty($jobConfig->getConfig()['scroller'])) {
         if (empty($this->defaultScroller)) {
             return new NoScroller();
         }
         if (!array_key_exists($this->defaultScroller, $this->scrollers)) {
             throw new UserException("Default scroller '{$this->defaultScroller}' does not exist");
         }
         return $this->scrollers[$this->defaultScroller];
     }
     $scrollerId = $jobConfig->getConfig()['scroller'];
     if (empty($this->scrollers[$scrollerId])) {
         throw new UserException("Scroller '{$scrollerId}' not set in API definitions. Scrollers defined: " . join(', ', array_keys($this->scrollers)));
     }
     return $this->scrollers[$scrollerId];
 }
 public function testProcess()
 {
     $cfg = JobConfig::create(['endpoint' => 'a', 'parseObject' => ['keyColumn' => 'id', 'path' => 'results']]);
     $module = new QualtricsPreParser();
     $response = (object) ['results' => (object) [1 => 'first', 2 => 'second'], 'otherArray' => ['a', 'b']];
     $data = $module->process($response, $cfg);
     self::assertEquals([(object) ['data' => 'first', 'id' => 1], (object) ['data' => 'second', 'id' => 2]], $data);
 }
Example #11
0
 /**
  * {@inheritdoc}
  */
 public function getNextRequest(ClientInterface $client, JobConfig $jobConfig, $response, $data)
 {
     $nextParam = Utils::getDataFromPath($this->responseParam, $response, '.');
     if (empty($nextParam)) {
         return false;
     } else {
         $config = $jobConfig->getConfig();
         if (!$this->includeParams) {
             $config['params'] = [];
         }
         if (!is_null($this->scrollRequest)) {
             $config = $this->createScrollRequest($config, $this->scrollRequest);
         }
         $config['params'][$this->queryParam] = $nextParam;
         return $client->createRequest($config);
     }
 }
Example #12
0
 public function testCreateRequest()
 {
     $arr = ['first' => 1, 'second' => 'two'];
     $jobConfig = JobConfig::create(['endpoint' => 'ep', 'params' => $arr]);
     $client = new RestClient(new Client());
     $request = $client->createRequest($jobConfig->getConfig());
     $expected = new RestRequest('ep', $arr);
     self::assertEquals($expected, $request);
 }
Example #13
0
 public function testGetConfig()
 {
     $configuration = new Configuration('./Tests/data/recursive', 'test', new Temp('test'));
     $config = $configuration->getConfig();
     $yml = Yaml::parse(file_get_contents('./Tests/data/recursive/config.yml'));
     $jobs = $config->getJobs();
     self::assertEquals(JobConfig::create($yml['parameters']['config']['jobs'][0]), reset($jobs));
     self::assertEquals($yml['parameters']['config']['outputBucket'], $config->getAttribute('outputBucket'));
 }
Example #14
0
 /**
  * {@inheritdoc}
  */
 public function getNextRequest(ClientInterface $client, JobConfig $jobConfig, $response, $data)
 {
     $nextUrl = Utils::getDataFromPath($this->urlParam, $response, '.');
     if (empty($nextUrl)) {
         return false;
     } else {
         $config = $jobConfig->getConfig();
         if (!$this->includeParams) {
             $config['params'] = [];
         }
         if (!$this->paramIsQuery) {
             $config['endpoint'] = $nextUrl;
         } else {
             // Create an array from the query string
             $responseQuery = Query::fromString(ltrim($nextUrl, '?'))->toArray();
             $config['params'] = array_replace($config['params'], $responseQuery);
         }
         return $client->createRequest($config);
     }
 }
    public function testProcessInsightsLifetime()
    {
        $cfg = JobConfig::create(['endpoint' => 'insights', 'dataField' => 'data', 'parser' => ['method' => 'facebook.insights']]);
        $module = new \Keboola\ExGenericModule\FacebookPreParser();
        $jsonResponse = <<<JSON
{
   "data": [
      {
         "name": "page_fan_adds_unique",
         "period": "lifetime",
         "values": [
            {
               "value": 1
            },
            {
               "value": 2
            }
         ],
         "title": "Daily New Likes",
         "id": "177057932317550/insights/page_fan_adds_unique"
      }
   ],
   "paging": {
      "previous": "prev",
      "next": "next"
   }
}
JSON;
        $response = json_decode($jsonResponse);
        $data = $module->process($response, $cfg);
        $this->assertEquals((object) ['data' => [(object) ['name' => 'page_fan_adds_unique', 'period' => 'lifetime', 'values' => [(object) ['id' => '177057932317550/insights/page_fan_adds_unique', 'key1' => '', 'key2' => '', 'end_time' => '', 'value' => 1], (object) ['id' => '177057932317550/insights/page_fan_adds_unique', 'key1' => '', 'key2' => '', 'end_time' => '', 'value' => 2]], 'title' => 'Daily New Likes', 'id' => '177057932317550/insights/page_fan_adds_unique']], 'paging' => (object) ['previous' => 'prev', 'next' => 'next']], $data);
    }
 /**
  * @param JobConfig $config
  * @return array
  */
 protected function buildParams(JobConfig $config)
 {
     $params = UserFunction::build($config->getParams(), ['attr' => $this->attributes, 'time' => $this->metadata['time']], $this->stringBuilder);
     $config->setParams($params);
     return $params;
 }
Example #17
0
 /**
  * @param JobConfig $config
  */
 public static function create(JobConfig $config)
 {
     $filters = empty($config->getConfig()['responseFilter']) ? [] : (is_array($config->getConfig()['responseFilter']) ? $config->getConfig()['responseFilter'] : [$config->getConfig()['responseFilter']]);
     $delimiter = empty($config->getConfig()['responseFilterDelimiter']) ? self::DEFAULT_DELIMITER : $config->getConfig()['responseFilterDelimiter'];
     return new self($filters, $delimiter);
 }
Example #18
0
 /**
  * {@inheritdoc}
  */
 public function getFirstRequest(ClientInterface $client, JobConfig $jobConfig)
 {
     return $client->createRequest($jobConfig->getConfig());
 }
Example #19
0
 /**
  * Create a child job with current client and parser
  * @param JobConfig $config
  * @return static
  */
 protected function createChild(JobConfig $config, array $parentResults)
 {
     // Clone the config to prevent overwriting the placeholder(s) in endpoint
     $job = new static(clone $config, $this->client, $this->parser);
     $params = [];
     $placeholders = !empty($config->getConfig()['placeholders']) ? $config->getConfig()['placeholders'] : [];
     if (empty($placeholders)) {
         Logger::log("WARNING", "No 'placeholders' set for '" . $config->getConfig()['endpoint'] . "'");
     }
     foreach ($placeholders as $placeholder => $field) {
         $params[$placeholder] = $this->getPlaceholder($placeholder, $field, $parentResults);
     }
     // Add parent params as well (for 'tagging' child-parent data)
     // Same placeholder in deeper nesting replaces parent value
     if (!empty($this->parentParams)) {
         $params = array_replace($this->parentParams, $params);
     }
     $job->setParams($params);
     $job->setParentResults($parentResults);
     return $job;
 }
Example #20
0
 public function testMergeResults()
 {
     Logger::setLogger($this->getLogger('testMergeResults', true));
     $configFirst = JobConfig::create(['endpoint' => '1st', 'dataType' => 'first']);
     $configTags = JobConfig::create(['endpoint' => '2nd', 'dataType' => 'tags']);
     $config = new Config('ex', 'test', []);
     $config->setAttributes(['mappings' => ['first' => ['id' => ['type' => 'column', 'mapping' => ['destination' => 'item_id']], 'tags' => ['type' => 'table', 'destination' => 'tags', 'tableMapping' => ['user' => ['mapping' => ['destination' => 'user', 'primaryKey' => true]], 'tag' => ['mapping' => ['destination' => 'tag', 'primaryKey' => true]]], 'parentKey' => ['disable' => true]]], 'tags' => ['user' => ['mapping' => ['destination' => 'user', 'primaryKey' => true]], 'tag' => ['mapping' => ['destination' => 'tag', 'primaryKey' => true]]]]]);
     $firstData = json_decode('[
         {
             "id": 1,
             "arr": [1,2,3]
         },
         {
             "id": 2,
             "arr": ["a","b","c"],
             "tags": [
                 {
                     "user": "******",
                     "tag": "tag1"
                 },
                 {
                     "user": "******",
                     "tag": "tag2"
                 }
             ]
         }
     ]');
     $secondData = json_decode('[
         {
             "user": "******",
             "tag": "tag3"
         },
         {
             "user": "******",
             "tag": "tag4"
         }
     ]');
     $parser = JsonMap::create($config);
     $parser->process($firstData, $configFirst->getDataType());
     $parser->process($secondData, $configTags->getDataType());
     self::assertEquals(['"user","tag"' . PHP_EOL, '"asd","tag1"' . PHP_EOL, '"asd","tag2"' . PHP_EOL, '"asd","tag3"' . PHP_EOL, '"asd","tag4"' . PHP_EOL], file($parser->getResults()['tags']));
 }
Example #21
0
 /**
  * @param JobConfig $jobConfig
  * @return int
  */
 protected function getLimit(JobConfig $jobConfig)
 {
     $params = $jobConfig->getParams();
     return empty($params[$this->limitParam]) ? $this->limit : $params[$this->limitParam];
 }
Example #22
0
 /**
  * @param object $job
  * @return JobConfig
  */
 protected function createJob($job)
 {
     if (!is_array($job)) {
         throw new UserException("Invalid format for job configuration.", 0, null, ['job' => $job]);
     }
     return JobConfig::create($job);
 }
Example #23
0
 /**
  * @return string
  */
 protected function getDataType()
 {
     $config = $this->config->getConfig();
     $type = !empty($config['dataType']) ? $config['dataType'] : $config['endpoint'];
     return $type;
 }
Example #24
0
 /**
  * @param JobConfig $job
  */
 public function addChildJob(self $job)
 {
     $this->childJobs[$job->getJobId()] = $job;
 }
Example #25
0
 public function testGetDataTypeFromEndpoint()
 {
     $jobConfig = JobConfig::create(['endpoint' => 'resources/res.json']);
     $job = $this->getMockForAbstractClass('Keboola\\Juicer\\Extractor\\Job', [$jobConfig, RestClient::create(), new Json(Parser::create($this->getLogger('job', true)))]);
     $this->assertEquals($jobConfig->getEndpoint(), $this->callMethod($job, 'getDataType', []));
 }