/** * 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 whether queries with different parameters return different hashes. */ public function testHashing() { $profile = new ProfileSummary(); $profile->setID('1'); $profile->setName('Foo'); $q = new GaDataQuery(); $q->setStartDate('2014-07-01'); $q->setEndDate('2014-08-01'); $q->setProfile($profile); $q->setMetrics(array('foo', 'bar', 'baz')); $hash = $q->getHash(); $q2 = clone $q; $this->assertEquals($hash, $q2->getHash()); // Changing the profile name shouldn't matter $q2->getProfile()->setName('Bar'); $this->assertEquals($hash, $q2->getHash()); // But changing its ID will $q2->getProfile()->setID('2'); $this->assertNotEquals($hash, $q2->getHash()); // Unless the change is just adding the prefix $q2->getProfile()->setID('ga:1'); $this->assertEquals($hash, $q2->getHash()); // Adding a new parameter should change the hash $q2->setDimensions('a,b,c'); $this->assertNotEquals($hash, $q2->getHash()); // Reset $q->setDimensions($q2->getDimensions()); $hash = $q->getHash(); $this->assertEquals($hash, $q2->getHash()); /* Using the same list elements but changing their order should change the hash. */ $q2->setMetrics(array('bar', 'baz', 'foo')); $this->assertNotEquals($hash, $q2->getHash()); // Reset $q2->setMetrics($q->getMetrics()); $this->assertEquals($hash, $q2->getHash()); // This is a special case and sholudn't affect the hash $q2->setSamplingLevel('NONE'); $this->assertEquals($hash, $q2->getHash()); }