cloud-8.x-2.0-beta1/modules/cloud_service_providers/aws_cloud/src/Service/Pricing/GoogleSpreadsheetService.php

modules/cloud_service_providers/aws_cloud/src/Service/Pricing/GoogleSpreadsheetService.php
<?php

namespace Drupal\aws_cloud\Service\Pricing;

use Google_Client;
use Google_Service_Exception;
use Google_Service_Drive;
use Google_Service_Drive_Permission;
use Google_Service_Sheets;
use Google_Service_Sheets_Spreadsheet;
use Google_Service_Sheets_ValueRange;
use Google_Service_Sheets_BatchUpdateSpreadsheetRequest;
use Google_Service_Sheets_Request;

use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * The google spreadsheet service.
 */
class GoogleSpreadsheetService {

  use StringTranslationTrait;

  /**
   * The Messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * The config factory.
   *
   * Subclasses should use the self::config() method, which may be overridden to
   * address specific needs when loading config, rather than this property
   * directly. See \Drupal\Core\Form\ConfigFormBase::config() for an example of
   * this.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The price data provider.
   *
   * @var \Drupal\aws_cloud\Service\pricing\InstanceTypePriceDataProvider
   */
  protected $dataProvider;

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   A configuration factory.
   * @param \Drupal\aws_cloud\Service\pricing\InstanceTypePriceDataProvider $data_provider
   *   The price data provider.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   */
  public function __construct(
    MessengerInterface $messenger,
    ConfigFactoryInterface $config_factory,
    InstanceTypePriceDataProvider $data_provider,
    TranslationInterface $string_translation
  ) {
    $this->messenger = $messenger;
    $this->configFactory = $config_factory;
    $this->dataProvider = $data_provider;
    $this->stringTranslation = $string_translation;
  }

  /**
   * Create or update a spreadsheet.
   *
   * @param string $spreadsheet_url
   *   The url of the spreadsheet.
   * @param string $region
   *   The name of an Amazon EC2 region.
   * @param string $title
   *   The title of the spreadsheet.
   *
   * @return string
   *   The url of the spreadsheet created.
   */
  public function createOrUpdate($spreadsheet_url, $region, $title) {
    try {
      $spreadsheet_id = NULL;
      if (!empty($spreadsheet_url)) {
        if (preg_match('/spreadsheets\/d\/(.+)\/edit/', $spreadsheet_url, $matches)) {
          $spreadsheet_id = $matches[1];
        }
      }

      // Get the API client and construct the service object.
      $client = $this->getClient();
      $service = new Google_Service_Sheets($client);

      // Create spreadsheet if spreadsheet ID is NULL.
      if (empty($spreadsheet_id)) {
        $spreadsheet = $this->createSpreadsheet($client, $service, $title);
        $spreadsheet_id = $spreadsheet->getSpreadsheetId();
      }
      else {
        $spreadsheet = $service->spreadsheets->get($spreadsheet_id);
      }

      // Add or update the sheet for region.
      $sheet = $this->findSheet($service, $spreadsheet, $region);
      if ($sheet == NULL) {
        $sheet = $this->createSheet($service, $spreadsheet, $region);
      }

      $sheet_id = $sheet->getProperties()->getSheetId();
      $sheet_title = $sheet->getProperties()->getTitle();

      // Append data.
      $values = $this->getValues(
        $this->dataProvider->getFields(),
        $this->dataProvider->getDataByRegion($region)
      );
      $request_body = new Google_Service_Sheets_ValueRange(['values' => $values]);
      $service->spreadsheets_values->update(
        $spreadsheet_id,
        $sheet_title . '!A1',
        $request_body,
        ['valueInputOption' => 'USER_ENTERED']
      );

      $requests = [];
      for ($i = 1; $i < count($values[0]); $i++) {
        $my_range = [
          'sheetId' => $sheet_id,
          'startRowIndex' => 1,
          'endRowIndex' => count($values),
          'startColumnIndex' => $i,
          'endColumnIndex' => $i + 1,
        ];
        $requests[] = new Google_Service_Sheets_Request([
          'addConditionalFormatRule' => [
            'rule' => [
              'ranges' => [$my_range],
              'gradientRule' => [
                'minpoint' => [
                  'color' => [
                    'green' => 1,
                    'red' => 0,
                  ],
                  'type' => 'MIN',
                ],
                'midpoint' => [
                  // Color rgb(255, 214, 102).
                  'color' => [
                    'red' => 1,
                    'green' => 0.84,
                    'blue' => 0.4,
                  ],
                  'type' => 'PERCENTILE',
                  'value' => '50',
                ],
                'maxpoint' => [
                  'color' => [
                    'green' => 0,
                    'red' => 1,
                  ],
                  'type' => 'MAX',
                ],
              ],
            ],
            'index' => 0,
          ],
        ]);
      }

      // Make header align to center.
      $requests[] = new Google_Service_Sheets_Request([
        'repeatCell' => [
          'cell' => [
            'userEnteredFormat' => [
              'horizontalAlignment' => 'CENTER',
              'verticalAlignment' => 'MIDDLE',
            ],
          ],
          'range' => [
            'sheetId' => $sheet_id,
            'startRowIndex' => 0,
            'endRowIndex' => 1,
            'startColumnIndex' => 0,
            'endColumnIndex' => count($values[0]),
          ],
          'fields' => 'userEnteredFormat',
        ],
      ]);

      // Update the font family to Lato.
      $requests[] = new Google_Service_Sheets_Request([
        'repeatCell' => [
          'cell' => [
            'userEnteredFormat' => [
              'textFormat' => [
                'fontFamily' => 'Lato',
              ],
            ],
          ],
          'range' => [
            'sheetId' => $sheet_id,
            'startRowIndex' => 0,
            'endRowIndex' => count($values),
            'startColumnIndex' => 0,
            'endColumnIndex' => count($values[0]),
          ],
          'fields' => 'userEnteredFormat.textFormat.fontFamily',
        ],
      ]);

      // Add basic filter.
      $requests[] = new Google_Service_Sheets_Request([
        'setBasicFilter' => [
          'filter' => [
            'range' => [
              'sheetId' => $sheet_id,
              'startRowIndex' => 0,
              'endRowIndex' => 1,
              'startColumnIndex' => 0,
              'endColumnIndex' => count($values[0]),
            ],
          ],
        ],
      ]);

      // Freeze column and row and update sheet name.
      $requests[] = new Google_Service_Sheets_Request([
        'updateSheetProperties' => [
          'properties' => [
            'sheetId' => $sheet_id,
            'gridProperties' => [
              'frozenRowCount' => 1,
              'frozenColumnCount' => 1,
            ],
            'title' => $region,
          ],
          'fields' => 'gridProperties.frozenRowCount,gridProperties.frozenColumnCount,title',
        ],
      ]);

      // Update column instance_type width.
      $requests[] = new Google_Service_Sheets_Request([
        'updateDimensionProperties' => [
          'range' => [
            'sheetId' => $sheet_id,
            'dimension' => 'COLUMNS',
            'startIndex' => 0,
            'endIndex' => 1,
          ],
          'properties' => [
            'pixelSize' => 120,
          ],
          'fields' => 'pixelSize',
        ],
      ]);

      $batch_update_request = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest(
        ['requests' => $requests]
      );
      $service->spreadsheets->batchUpdate($spreadsheet_id, $batch_update_request);

      return $spreadsheet->getSpreadsheetUrl() . '#gid=' . $sheet_id;
    }
    catch (Google_Service_Exception $e) {
      foreach ($e->getErrors() as $error) {
        $this->messenger->addError(
          $this->t(
            'Failed to create spreadsheet due to the Google_Service_Exception with error "@message"',
            ['@message' => $error['message']]
          )
        );
      }
    }
    catch (\Exception $e) {
      $this->messenger->addError(
        $this->t(
          'Failed to create spreadsheet due to the Exception with error "@message"',
          ['@message' => $e->getMessage()]
        )
      );
    }

    return '';
  }

  /**
   * Delete a spreadsheet.
   *
   * @param string $spreadsheet_url
   *   The url of a spreadsheet.
   */
  public function delete($spreadsheet_url) {
    try {
      $client = $this->getClient();
      $drive_service = new Google_Service_Drive($client);

      if (preg_match('/spreadsheets\/d\/(.+)\/edit/', $spreadsheet_url, $matches)) {
        $spreadsheet_id = $matches[1];
        $drive_service->files->delete($spreadsheet_id);
      }
    }
    catch (Google_Service_Exception $e) {
      foreach ($e->getErrors() as $error) {
        $this->messenger->addError(
          $this->t(
            'Failed to delete spreadsheet due to the Google_Service_Exception with error "@message"',
            ['@message' => $error['message']]
          )
        );
      }
    }
    catch (\Exception $e) {
      $this->messenger->addError(
        $this->t(
          'Failed to delete spreadsheet due to the Exception with error "@message"',
          ['@message' => $e->getMessage()]
        )
      );
    }
  }

  /**
   * Get client.
   *
   * @return \Google_Client
   *   Google client.
   */
  private function getClient() {
    $client = new Google_Client();
    $client->setApplicationName('Cloud');
    $client->setScopes([
      Google_Service_Sheets::SPREADSHEETS,
      Google_Service_Drive::DRIVE,
    ]);

    $client->setAuthConfig(aws_cloud_google_credential_file_path());
    $client->setAccessType('offline');
    return $client;
  }

  /**
   * Get values for spreadsheet.
   *
   * @param array $fields
   *   Fields.
   * @param array $data
   *   Data.
   *
   * @return array
   *   The values for spreadsheet.
   */
  private function getValues(array $fields, array $data) {
    $headers = array_map(function ($item) {
      return str_replace('<br>', "\n", $item->render());
    }, array_values($fields));

    $rows = array_map(function ($item) {
      return array_values($item);
    }, $data);

    return array_merge([$headers], array_values($rows));
  }

  /**
   * Create a spreadsheet and set the permission.
   *
   * @param \Google_Client $client
   *   The google API client.
   * @param \Google_Service_Sheets $service
   *   The google spreadsheet service.
   * @param string $title
   *   The title of the spreadsheet.
   *
   * @return \Google_Service_Sheets_Spreadsheet
   *   The new spreadsheet created.
   */
  private function createSpreadsheet(
    Google_Client $client,
    Google_Service_Sheets $service,
    $title
  ) {
    $spreadsheet = new Google_Service_Sheets_Spreadsheet([
      'properties' => [
        'title' => $title,
      ],
    ]);
    $spreadsheet = $service->spreadsheets->create($spreadsheet);
    $spreadsheet_id = $spreadsheet->getSpreadsheetId();

    // Share the file.
    $drive_service = new Google_Service_Drive($client);
    $userPermission = new Google_Service_Drive_Permission([
      'type' => 'anyone',
      'role' => 'reader',
    ]);
    $drive_service->permissions->create(
      $spreadsheet_id,
      $userPermission,
      ['fields' => 'id']
    );

    return $spreadsheet;
  }

  /**
   * Find the sheet with the same name as the region's name.
   *
   * @param \Google_Service_Sheets $service
   *   The google spreadsheet service.
   * @param \Google_Service_Sheets_Spreadsheet $spreadsheet
   *   The spreadsheet.
   * @param string $region
   *   The region.
   *
   * @return \Google_Service_Sheets_Sheet
   *   The sheet found. NULL if there is no sheet found.
   */
  private function findSheet(
    Google_Service_Sheets $service,
    Google_Service_Sheets_Spreadsheet $spreadsheet,
    $region
  ) {
    $spreadsheet_id = $spreadsheet->getSpreadsheetId();
    $sheets = $spreadsheet->getSheets();
    foreach ($sheets as $sheet) {
      if ($sheet->getProperties()->getTitle() == $region) {
        return $sheet;
      }
    }

    // If there is only a default sheet, use it and update title.
    if (count($sheets) == 1 && $sheets[0]->getProperties()->getTitle() == 'Sheet1') {
      $request = new Google_Service_Sheets_Request([
        'updateSheetProperties' => [
          'properties' => [
            'sheetId' => 0,
            'title' => $region,
          ],
          'fields' => 'title',
        ],
      ]);

      $batch_update_request = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest(
        ['requests' => [$request]]
      );
      $service->spreadsheets->batchUpdate($spreadsheet_id, $batch_update_request);
      $sheets[0]->getProperties()->setTitle($region);
      return $sheets[0];
    }

    return NULL;
  }

  /**
   * Find the place to insert the sheet of the region.
   *
   * @param \Google_Service_Sheets_Spreadsheet $spreadsheet
   *   The spreadsheet.
   * @param string $region
   *   The region.
   *
   * @return int
   *   The place to insert.
   */
  private function findSheetInsertIndex(
    Google_Service_Sheets_Spreadsheet $spreadsheet,
    $region
  ) {
    $sheets = $spreadsheet->getSheets();
    foreach ($sheets as $sheet) {
      if ($sheet->getProperties()->getTitle() > $region) {
        return $sheet->getProperties()->getIndex();
      }
    }

    return $sheets[count($sheets) - 1]->getProperties()->getIndex() + 1;
  }

  /**
   * Create a sheet.
   *
   * @param \Google_Service_Sheets $service
   *   The google spreadsheet service.
   * @param \Google_Service_Sheets_Spreadsheet $spreadsheet
   *   The spreadsheet.
   * @param string $region
   *   The region.
   *
   * @return \Google_Service_Sheets_Sheet
   *   The sheet created.
   */
  private function createSheet(
    Google_Service_Sheets $service,
    Google_Service_Sheets_Spreadsheet $spreadsheet,
    $region
  ) {
    $spreadsheet_id = $spreadsheet->getSpreadsheetId();

    // Create a sheet.
    $request = new Google_Service_Sheets_Request([
      'addSheet' => [
        'properties' => [
          'title' => $region,
          'index' => $this->findSheetInsertIndex($spreadsheet, $region),
        ],
      ],
    ]);

    $batch_update_request = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest(
      ['requests' => [$request]]
    );
    $response = $service->spreadsheets->batchUpdate($spreadsheet_id, $batch_update_request);
    return $response->getReplies()[0]->getAddSheet();
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc