/** * Performs a Google Analytics query with the given * Google\Analytics\GaDataQuery object and returns the result as a * Google\Analytics\GaData object, or boolean false if the query's data * has been exhausted. * * @param Google\Analytics\GaDataQuery $query * @return Google\Analytics\GaData, boolean */ public function query(GaDataQuery $query) { $query->setAPIInstance($this); $totalResults = $query->getTotalResults(); do { /* If the given query is already active, meaning that we have made a call for its first page of results already, don't pass any arguments to $this->_makeRequest(). */ $hash = $query->getHash(); if ($hash == $this->_activeQuery) { if ($totalResults !== null && $this->_totalRows >= $totalResults) { // No reason to continue $response = false; break; } $response = $this->_makeRequest(); } else { $this->_activeQuery = $hash; $this->_totalRows = 0; $response = $this->_makeRequest(new APIRequest('data/ga', $query->getAsArray())); } /* The response will be boolean false if the query had data, but it has been exhausted. It will be a Google\Analytics\GaData object with no rows if the query returned no data at all. If there's no chance of achieving a response by iterating, we'll consider the operation as having retrieved a response, even if no data came back. */ if ($response && $response->getRows() || !$query instanceof IterativeGaDataQuery || !$query->iterate()) { $gotResponse = true; } else { $gotResponse = false; } } while (!$gotResponse); if ($response) { if ($query->getSamplingLevel() == GaDataQuery::SAMPLING_LEVEL_NONE && $response->containsSampledData()) { throw new SamplingException('The response contains sampled data.'); } /* I have to do this here instead of allowing it to happen automatically so that I can pass the API instance as an argument. */ $response->setColumnHeaders($this->_responseParsed['columnHeaders'], $this); // I also want the rows object to be aware of the columns object $rows = $response->getRows(); $rows->setColumnHeaders($response->getColumnHeaders()); $rowCount = count($rows); if ($rowCount) { $this->_totalRows += $rowCount; if ($totalResults !== null) { $surplus = $this->_totalRows - $totalResults; if ($surplus > 0) { /* Even though we already got the data, behave as we were asked and lop off the extra rows. */ $rows->discard($surplus); } } } } else { $this->_activeQuery = null; } return $response; }
/** * Tests to make sure the array representation of the query is accurate. */ public function testArrayRepresentation() { $q = new GaDataQuery(); /* It shouldn't be possible to get the query's array representation until the minimum required properties have been set. */ $this->assertThrows(__NAMESPACE__ . '\\LogicException', array($q, 'getAsArray')); $profile = new ProfileSummary(); $profile->setID('123'); $profile->setName('foo'); $q->setProfile($profile); $this->assertThrows(__NAMESPACE__ . '\\LogicException', array($q, 'getAsArray')); $q->setStartDate('2015-03-15'); $this->assertThrows(__NAMESPACE__ . '\\LogicException', array($q, 'getAsArray')); $q->setEndDate('2015-03-31'); $this->assertThrows(__NAMESPACE__ . '\\LogicException', array($q, 'getAsArray')); $q->setMetrics(array('a_metric', 'another_metric')); $expected = array('ids' => 'ga:123', 'start-date' => '2015-03-15', 'end-date' => '2015-03-31', 'metrics' => 'ga:a_metric,ga:another_metric', 'start-index' => 1, 'max-results' => GOOGLE_ANALYTICS_API_PAGE_SIZE); $this->assertEquals($expected, $q->getAsArray()); $q->setMaxResults(234); $expected['max-results'] = 234; $this->assertEquals($expected, $q->getAsArray()); $q->setStartIndex(1000); $expected['start-index'] = 1000; $this->assertEquals($expected, $q->getAsArray()); $q->setMetrics('foo,bar,baz'); $expected['metrics'] = 'ga:foo,ga:bar,ga:baz'; $this->assertEquals($expected, $q->getAsArray()); $profile = new ProfileSummary(); $profile->setID('987987'); $profile->setName('asdf'); $q->setProfile($profile); $expected['ids'] = 'ga:987987'; $this->assertEquals($expected, $q->getAsArray()); $q->setStartDate('2000-01-01'); $q->setEndDate('2000-12-31'); $expected['start-date'] = '2000-01-01'; $expected['end-date'] = '2000-12-31'; $this->assertEquals($expected, $q->getAsArray()); $q->setSamplingLevel(GaDataQuery::SAMPLING_LEVEL_FASTER); $expected['samplingLevel'] = 'FASTER'; $this->assertEquals($expected, $q->getAsArray()); // Note the special case here $q->setSamplingLevel(GaDataQuery::SAMPLING_LEVEL_NONE); unset($expected['samplingLevel']); $this->assertEquals($expected, $q->getAsArray()); $q->setDimensions(array('asdfasdf', 'oijoij')); $expected['dimensions'] = 'ga:asdfasdf,ga:oijoij'; $this->assertEquals($expected, $q->getAsArray()); $sort = new GaDataSortOrder(); $sort->addField('foo'); $sort->addField('bar', SORT_DESC); $q->setSort($sort); $expected['sort'] = (string) $sort; $this->assertEquals($expected, $q->getAsArray()); $filter = new GaDataFilterCollection(GaDataFilterCollection::OP_AND, new GaDataFilterCollection(GaDataFilterCollection::OP_OR, new GaDataConditionalExpression('foo', GaDataConditionalExpression::OP_GE, 1)), new GaDataFilterCollection(GaDataFilterCollection::OP_OR, new GaDataConditionalExpression('bar', GaDataConditionalExpression::OP_NE, 'baz'))); $q->setFilter($filter); $expected['filters'] = (string) $filter; $this->assertEquals($expected, $q->getAsArray()); $segment = new GaDataSegment(new GaDataSegmentConditionGroup(new GaDataSegmentSimpleCondition('foo', GaDataSegmentSimpleCondition::OP_LT, 20)), GaDataSegment::SCOPE_USERS, new GaDataSegmentSequence(new GaDataSegmentSequenceCondition('bar', GaDataSegmentSequenceCondition::OP_EQ, 'baz'), new GaDataSegmentSequenceCondition('baz', GaDataSegmentSequenceCondition::OP_GT, 0, GaDataSegmentSequenceCondition::OP_FOLLOWED_BY_IMMEDIATE)), GaDataSegment::SCOPE_SESSIONS); $q->setSegment($segment); $expected['segment'] = (string) $segment; $this->assertEquals($expected, $q->getAsArray()); }