コード例 #1
0
ファイル: API.class.php プロジェクト: performics/ga-cli-api
 /**
  * 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;
 }
コード例 #2
0
 /**
  * Helper method to create a single query instance from an associative
  * array of command-line arguments or XML configuration values.
  *
  * @param array $args
  * @return Google\Analytics\GaDataQuery
  */
 private static function _getQuery(array $args)
 {
     if (!isset($args['profile-name']) && !isset($args['profile-id'])) {
         throw new InvalidArgumentException('A profile name or ID must be specified.');
     }
     if (!isset($args['metric'])) {
         throw new InvalidArgumentException('At least one metric must be specified.');
     }
     if (!isset($args['start-date']) || !isset($args['end-date'])) {
         throw new InvalidArgumentException('A start date and an end date must be specified.');
     }
     // See whether we have to resolve date shortcuts
     $dateKeys = array('start-date', 'end-date');
     foreach ($dateKeys as $key) {
         if (preg_match('/^[A-Z]+_[_A-Z]+_[A-Z]+$/', $args[$key])) {
             $r = new \ReflectionClass(__NAMESPACE__ . '\\GaDataQuery');
             try {
                 $args[$key] = $r->getConstant($args[$key]);
             } catch (\ReflectionException $e) {
                 throw new InvalidArgumentException('"' . $args[$key] . '" is not a valid date shortcut.');
             }
         }
     }
     if (isset($args['split-queries-by'])) {
         $interval = strtoupper($args['split-queries-by']);
         if ($interval != 'DAY' && $interval != 'WEEK' && $interval != 'MONTH' && $interval != 'YEAR') {
             throw new InvalidArgumentException('Queries may only be split by day, week, month, or year.');
         }
         $q = new DateRangeGaDataQuery(null, $args['start-date'], $args['end-date'], new \DateInterval('P1' . $interval[0]));
         $q->setIterativeName(ucfirst(strtolower($interval)));
         if (isset($args['date-format-string'])) {
             $q->setFormatString($args['date-format-string']);
         }
     } else {
         $q = new GaDataQuery();
         $q->setStartDate($args['start-date']);
         $q->setEndDate($args['end-date']);
     }
     if (isset($args['name'])) {
         $q->setName($args['name']);
     }
     if (isset($args['profile-id'])) {
         $q->setProfile($args['profile-id']);
     } else {
         $q->setProfileName($args['profile-name']);
     }
     $q->setMetrics(explode(',', $args['metric']));
     if (isset($args['dimension'])) {
         $q->setDimensions(explode(',', $args['dimension']));
     }
     if (isset($args['sort'])) {
         $sort = new GaDataSortOrder();
         $sortStrings = explode(',', $args['sort']);
         foreach ($sortStrings as $sortString) {
             if (!strlen($sortString)) {
                 continue;
             }
             if ($sortString[0] == '-') {
                 $order = SORT_DESC;
                 $sortString = substr($sortString, 1);
             } else {
                 $order = SORT_ASC;
             }
             $sort->addField($sortString, $order);
         }
         $q->setSort($sort);
     }
     if (isset($args['limit'])) {
         $q->setTotalResults($args['limit']);
     }
     if (isset($args['filter'])) {
         $q->setFilter($args['filter']);
     }
     if (isset($args['segment'])) {
         $q->setSegment($args['segment']);
     }
     if (isset($args['sampling-level'])) {
         $q->setSamplingLevel(strtoupper($args['sampling-level']));
     }
     return $q;
 }
コード例 #3
0
 /**
  * Tests instantiation from command-line arguments and the equivalent XML.
  */
 public function testInstantiation()
 {
     $args = array('profile-id' => '12345', 'email' => '*****@*****.**', 'start-date' => '2015-01-01', 'end-date' => '2015-01-31', 'metric' => 'foo');
     $expectedQuery = new GaDataQuery();
     $expectedQuery->setProfile($args['profile-id']);
     $expectedQuery->setStartDate($args['start-date']);
     $expectedQuery->setEndDate($args['end-date']);
     $expectedQuery->setMetrics($args['metric']);
     $this->_assertConfiguration($expectedQuery, $args);
     unset($args['profile-id']);
     $args['profile-name'] = 'Foo Industries Inc.';
     $expectedQuery = new GaDataQuery();
     $expectedQuery->setProfileName($args['profile-name']);
     $expectedQuery->setStartDate($args['start-date']);
     $expectedQuery->setEndDate($args['end-date']);
     $expectedQuery->setMetrics($args['metric']);
     $this->_assertConfiguration($expectedQuery, $args);
     $args['metric'] = 'foo,bar';
     $expectedQuery->setMetrics(array('foo', 'bar'));
     $this->_assertConfiguration($expectedQuery, $args);
     $args['dimension'] = 'baz';
     $expectedQuery->setDimensions($args['dimension']);
     $this->_assertConfiguration($expectedQuery, $args);
     $args['dimension'] = 'baz,borg';
     $expectedQuery->setDimensions(array('baz', 'borg'));
     $this->_assertConfiguration($expectedQuery, $args);
     $args['sort'] = 'foo';
     $sortOrder = new GaDataSortOrder();
     $sortOrder->addField('foo');
     $expectedQuery->setSort($sortOrder);
     $this->_assertConfiguration($expectedQuery, $args);
     $args['sort'] = 'foo,-baz';
     $sortOrder->addField('baz', SORT_DESC);
     // No need to set the sort order again, since it's an object
     $this->_assertConfiguration($expectedQuery, $args);
     $args['filter'] = 'ga:foo>=1';
     /* It's a bit counter-intuitive, but the filter string above will be
        interpreted as a Google\Analytics\GaDataFilterCollection object with
        another instance of the same object as the sole member; this member
        will have the conditional expression itself and the logical operator
        "," (OR). This is what allows the mixing or ORs and ANDs. */
     $filter = new GaDataFilterCollection(GaDataFilterCollection::OP_AND, new GaDataFilterCollection(GaDataFilterCollection::OP_OR, new GaDataConditionalExpression('foo', GaDataConditionalExpression::OP_GE, 1)));
     $expectedQuery->setFilter($filter);
     $this->_assertConfiguration($expectedQuery, $args);
     $args['filter'] .= ';ga:bar!=baz';
     $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')));
     $expectedQuery->setFilter($filter);
     $this->_assertConfiguration($expectedQuery, $args);
     $args['filter'] = 'ga:foo<20,ga:bar==baz';
     $filter = new GaDataFilterCollection(GaDataFilterCollection::OP_AND, new GaDataFilterCollection(GaDataFilterCollection::OP_OR, new GaDataConditionalExpression('foo', GaDataConditionalExpression::OP_LT, 20), new GaDataConditionalExpression('bar', GaDataConditionalExpression::OP_EQ, 'baz')));
     $expectedQuery->setFilter($filter);
     $this->_assertConfiguration($expectedQuery, $args);
     // Segments can be numeric IDs
     $args['segment'] = '-2';
     $expectedQuery->setSegment(-2);
     $this->_assertConfiguration($expectedQuery, $args);
     // The can also be strings
     $args['segment'] = 'users::condition::ga:foo<20';
     $expectedQuery->setSegment($args['segment']);
     $this->_assertConfiguration($expectedQuery, $args);
     /* They can also be objects, but at the moment this isn't really
        testable because I have put off implementing
        Google\Analytics\GaDataSegment::createFromString().
        $args['segment'] = 'users::condition::ga:foo<20';
        $segment = new GaDataSegment(
            new GaDataSegmentConditionGroup(
                new GaDataSegmentSimpleCondition(
                    'foo', GaDataSegmentSimpleCondition::OP_LT, 20
                )
            ),
            GaDataSegment::SCOPE_USERS
        );
        $expectedQuery->setSegment($segment);
        $this->_assertConfiguration($expectedQuery, $args);
        $args['segment'] = 'users::condition::ga:foo<20;sessions::sequence::ga:bar==baz->ga:baz>0';
        $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
        );
        $this->_assertConfiguration($expectedQuery, $args);
        */
     $args['sampling-level'] = 'higher_precision';
     $expectedQuery->setSamplingLevel(GaDataQuery::SAMPLING_LEVEL_HIGHER_PRECISION);
     $this->_assertConfiguration($expectedQuery, $args);
     $args['name'] = 'Some report name';
     $expectedQuery->setName($args['name']);
     $this->_assertConfiguration($expectedQuery, $args);
     /* If we are splitting queries, we should get a
        Google\Analytics\DateRangeGaDataQuery object. */
     $args['split-queries-by'] = 'day';
     $expectedDateRangeQuery = new DateRangeGaDataQuery();
     $expectedDateRangeQuery->setSummaryStartDate($expectedQuery->getStartDate());
     $expectedDateRangeQuery->setSummaryEndDate($expectedQuery->getEndDate());
     $expectedDateRangeQuery->setIterationInterval(new \DateInterval('P1D'));
     $expectedDateRangeQuery->setIterativeName('Day');
     $expectedDateRangeQuery->setMetrics($expectedQuery->getMetrics());
     $expectedDateRangeQuery->setProfileName($args['profile-name']);
     $expectedDateRangeQuery->setDimensions($expectedQuery->getDimensions());
     $expectedDateRangeQuery->setSort($expectedQuery->getSort());
     $expectedDateRangeQuery->setFilter($expectedQuery->getFilter());
     $expectedDateRangeQuery->setSegment($expectedQuery->getSegment());
     $expectedDateRangeQuery->setSamplingLevel($expectedQuery->getSamplingLevel());
     $expectedDateRangeQuery->setName($expectedQuery->getName());
     $this->_assertConfiguration($expectedDateRangeQuery, $args);
     /* If we use multiple instances of certain parameters, we should get a
        Google\Analytics\GaDataQueryCollection object. All parameters that are
        supplied as a single instance will be shared by all individual queries
        in the collection. */
     unset($args['split-queries-by']);
     $args['name'] = array($args['name']);
     $args['name'][] = 'Some other report name';
     $expectedQuery2 = clone $expectedQuery;
     $expectedQuery2->setName('Some other report name');
     $expectedQueryCollection = new GaDataQueryCollection($expectedQuery, $expectedQuery2);
     $this->_assertConfiguration($expectedQueryCollection, $args);
     // An underscore is treated as a placeholder and ignored
     $args = array('profile-id' => '12345', 'start-date' => '2015-01-01', 'end-date' => '2015-01-31', 'email' => '*****@*****.**', 'metric' => array('foo', 'bar'), 'segment' => array('users::condition::ga:foo<20', '_'), 'group-name' => 'Some name');
     $expectedQuery = new GaDataQuery();
     $expectedQuery->setProfile($args['profile-id']);
     $expectedQuery->setStartDate($args['start-date']);
     $expectedQuery->setEndDate($args['end-date']);
     $expectedQuery2 = clone $expectedQuery;
     $expectedQuery->setMetrics($args['metric'][0]);
     $expectedQuery2->setMetrics($args['metric'][1]);
     $expectedQuery->setSegment($args['segment'][0]);
     $expectedQueryCollection = new GaDataQueryCollection($expectedQuery, $expectedQuery2);
     $expectedQueryCollection->setName($args['group-name']);
     $this->_assertConfiguration($expectedQueryCollection, $args);
     // Unless the underscore is escaped
     $args['sort'] = array('foo', '\\_');
     $sortOrder = new GaDataSortOrder();
     $sortOrder->addField('foo');
     $expectedQuery->setSort($sortOrder);
     $sortOrder = new GaDataSortOrder();
     $sortOrder->addField('_');
     $expectedQuery2->setSort($sortOrder);
     $this->_assertConfiguration($expectedQueryCollection, $args);
     // We can split by an interval in any of the queries we get back
     $args['metric'][] = $args['metric'][0];
     $args['segment'][] = $args['segment'][0];
     $args['sort'][] = $args['sort'][0];
     $args['split-queries-by'] = array('_', '_', 'week');
     $expectedQuery3 = new DateRangeGaDataQuery();
     $expectedQuery3->setSummaryStartDate($expectedQuery->getStartDate());
     $expectedQuery3->setSummaryEndDate($expectedQuery->getEndDate());
     $expectedQuery3->setIterationInterval(new \DateInterval('P1W'));
     $expectedQuery3->setIterativeName('Week');
     $expectedQuery3->setProfile($args['profile-id']);
     $expectedQuery3->setMetrics($expectedQuery->getMetrics());
     $expectedQuery3->setSegment($expectedQuery->getSegment());
     $expectedQuery3->setSort($expectedQuery->getSort());
     $expectedQueryCollection = new GaDataQueryCollection($expectedQuery, $expectedQuery2, $expectedQuery3);
     $expectedQueryCollection->setName($args['group-name']);
     $this->_assertConfiguration($expectedQueryCollection, $args);
     /* Make sure we get exceptions where necessary, e.g. the lack of a
        profile specifier. */
     unset($args['profile-id']);
     $this->assertThrows(__NAMESPACE__ . '\\InvalidArgumentException', array(__NAMESPACE__ . '\\QueryConfiguration', 'createFromCommandLineArgs'), array($args));
     $this->assertEquals('A profile name or ID must be specified.', $this->_lastException->getMessage());
     // Or inconsistent parameter counts
     $args['profile-id'] = '12345';
     $args['sort'][] = 'asdf';
     $this->assertThrows(__NAMESPACE__ . '\\InvalidArgumentException', array(__NAMESPACE__ . '\\QueryConfiguration', 'createFromCommandLineArgs'), array($args));
     $this->assertContains('Please ensure that all arguments are invoked either a ' . 'single time only or the same number of times.', $this->_lastException->getMessage());
 }
コード例 #4
0
 /**
  * Tests to make sure the email subject line reflects the name property
  * where present.
  */
 public function testEmailSubject()
 {
     $q = new GaDataQuery();
     $q->setStartDate('2013-07-28');
     $q->setEndDate('2013-11-03');
     $profile = new ProfileSummary();
     $profile->setID('123');
     $profile->setName('Foo');
     $q->setProfile($profile);
     $this->assertEquals('Google Analytics report for profile "Foo" for 2013-07-28 through 2013-11-03', $q->getEmailSubject());
     $q->setName('Bar');
     $this->assertEquals('Google Analytics report "Bar" for 2013-07-28 through 2013-11-03', $q->getEmailSubject());
 }