View source
<?php
namespace Drupal\google_analytics_reports\Plugin\views\query;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Url;
use Drupal\Component\Utility\Html;
use Drupal\Core\State\StateInterface;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\ResultRow;
use Drupal\views\ViewExecutable;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
class GoogleAnalyticsQuery extends QueryPluginBase {
use StringTranslationTrait;
protected $tableQueue = [];
protected $fields = [];
protected $fieldAliases = [];
protected $where = [];
protected $orderby = [];
protected $groupOperator = 'AND';
public $moduleHandler;
public $configFactory;
protected $messenger;
protected $state;
public function __construct(array $configuration, $plugin_id, $plugin_definition, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, StateInterface $state, MessengerInterface $messenger) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->moduleHandler = $module_handler;
$this->configFactory = $config_factory;
$this->state = $state;
$this->messenger = $messenger;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('module_handler'), $container
->get('config.factory'), $container
->get('state'), $container
->get('messenger'));
}
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
$this
->unpackOptions($this->options, $options);
}
public function addField($table, $field, $alias = '', array $params = []) {
if ($table == $this->view->storage
->get('base_table') && $field == $this->view->storage
->get('base_field') && empty($alias)) {
$alias = $this->view->storage
->get('base_field');
}
if ($table && empty($this->tableQueue[$table])) {
$this
->ensureTable($table);
}
if (!$alias && $table) {
$alias = $table . '_' . $field;
}
$alias = $alias ? $alias : $field;
$alias = substr($alias, 0, 60);
$field_info = [
'field' => $field,
'table' => $table,
'alias' => $alias,
] + $params;
$base = $alias;
$counter = 0;
while (!empty($this->fields[$alias]) && $this->fields[$alias] != $field_info) {
$field_info['alias'] = $alias = $base . '_' . ++$counter;
}
if (empty($this->fields[$alias])) {
$this->fields[$alias] = $field_info;
}
$this->fieldAliases[$table][$field] = $alias;
return $alias;
}
public function addWhere($group, $field, $value = NULL, $operator = NULL) {
if (empty($group)) {
$group = 0;
}
if (!isset($this->where[$group])) {
$this
->setWhereGroup('AND', $group);
}
$this->where[$group]['conditions'][] = [
'field' => $field,
'value' => $value,
'operator' => $operator,
];
}
public function addOrderBy($table, $field = NULL, $order = 'ASC', $alias = '', array $params = []) {
$this->orderby[] = [
'field' => $field,
'direction' => strtoupper($order) == 'DESC' ? '-' : '',
];
}
public function query($get_count = FALSE) {
$available_fields = google_analytics_reports_get_fields();
$query = [];
foreach ($this->fields as $field) {
$field_name = google_analytics_reports_variable_to_custom_field($field['field']);
if ($available_fields[$field_name]) {
$type = $available_fields[$field_name]->type;
$type = $type == 'dimension' ? 'dimensions' : 'metrics';
$query[$type][] = 'ga:' . $field['field'];
}
}
$filters = [];
if (isset($this->where)) {
foreach ($this->where as $where_group => $where) {
foreach ($where['conditions'] as $condition) {
$field_name = google_analytics_reports_variable_to_custom_field($condition['field']);
if ($field_name == '.start_date' || $field_name == '.end_date' || $field_name == 'profile_id') {
$field_name = ltrim($field_name, '.');
$query[$field_name] = intval($condition['value']);
}
elseif (!empty($available_fields[$field_name])) {
$filters[$where_group][] = 'ga:' . $condition['field'] . $condition['operator'] . $condition['value'];
}
}
if (!empty($filters[$where_group])) {
$glue = $where['type'] == 'AND' ? ';' : ',';
$filters[$where_group] = implode($glue, $filters[$where_group]);
}
}
}
if (!empty($filters)) {
$glue = $this->groupOperator == 'AND' ? ';' : ',';
$query['filters'] = implode($glue, $filters);
}
if (isset($this->orderby)) {
foreach ($this->orderby as $field) {
$query['sort_metric'][] = $field['direction'] . 'ga:' . $field['field'];
}
}
if (!empty($this->options['reports_profile']) && !empty($this->options['profile_id'])) {
$query['profile_id'] = $this->options['profile_id'];
}
return $query;
}
public function alter(ViewExecutable $view) {
$this->moduleHandler
->invokeAll('views_query_alter', [
$view,
$this,
]);
}
public function build(ViewExecutable $view) {
$this->view = $view;
$view
->initPager();
$view->pager
->query();
$view->build_info['query'] = $this
->query();
$view->build_info['count_query'] = $this
->query(TRUE);
}
public function execute(ViewExecutable $view) {
if (!$this->state
->get('google_analytics_reports_api.access_token')) {
$this->messenger
->addMessage($this
->t('You must <a href=":url">authorize your site</a> to use your Google Analytics account before you can view reports.', [
':url' => Url::fromRoute('google_analytics_reports_api.settings')
->toString(),
]));
return;
}
$query = $view->build_info['query'];
$count_query = $view->build_info['count_query'];
$start = microtime(TRUE);
$count_query['max_results'] = 9999;
$count_query['start_index'] = 1;
$count_feed = google_analytics_reports_api_report_data($count_query);
if (!empty($count_feed->results->rows)) {
$view->pager->total_items = count($count_feed->results->rows);
$view->pager
->updatePageInfo();
if (!empty($this->limit) || !empty($this->offset)) {
$query['max_results'] = intval(!empty($this->limit) ? $this->limit : 1000);
$query['start_index'] = intval(!empty($this->offset) ? $this->offset : 0) + 1;
}
$feed = google_analytics_reports_api_report_data($query);
$rows = $feed->results->rows;
$views_result = [];
$count = 0;
foreach ($rows as $row) {
$row['index'] = $count;
$views_result[] = new ResultRow($row);
$count++;
}
$view->result = isset($views_result) ? $views_result : [];
$view->execute_time = microtime(TRUE) - $start;
if ($view->pager
->usePager()) {
$view->total_rows = $view->pager
->getTotalItems();
}
$view->build_info['query'] = print_r($feed->results->query, TRUE);
}
else {
$view->build_info['query'] = '';
if (!empty($count_feed->response->data)) {
$response_data = json_decode($count_feed->response->data);
if (isset($response_data['error']['message'])) {
$this->messenger
->addMessage(Html::escape($response_data['error']['message']), 'error');
}
}
}
}
public function defineOptions() {
$options = parent::defineOptions();
$options['reports_profile'] = [
'default' => FALSE,
'translatable' => FALSE,
'bool' => TRUE,
];
$options['profile_id'] = [
'default' => FALSE,
];
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$profile_list = google_analytics_reports_api_profiles_list();
$profile_info = '';
if (isset($profile_list['current_profile'])) {
$profile_info = parse_url($profile_list['current_profile']->websiteUrl, PHP_URL_HOST) . ' - ' . $profile_list['current_profile']->name . ' (' . $profile_list['current_profile']->id . ')';
}
if ($profile_list) {
$form['reports_profile'] = [
'#title' => $this
->t('Use another reports profile'),
'#description' => $this
->t('This view will use another reports profile rather than system default profile: %profile.', [
'%profile' => $profile_info,
]),
'#type' => 'checkbox',
'#default_value' => !empty($this->options['reports_profile']),
];
$form['profile_id'] = [
'#type' => 'select',
'#title' => $this
->t('Reports profile'),
'#options' => $profile_list['options'],
'#description' => $this
->t('Choose your Google Analytics profile.'),
'#default_value' => $this->options['profile_id'],
'#dependency' => [
'edit-query-options-reports-profile' => '1',
],
];
}
}
public function ensureTable($table, $relationship = NULL, $join = NULL) {
}
}