apigee_m10n-8.x-1.7/src/Controller/PrepaidBalanceXControllerBase.php
src/Controller/PrepaidBalanceXControllerBase.php
<?php
/*
* Copyright 2021 Google Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
namespace Drupal\apigee_m10n\Controller;
use Apigee\Edge\Api\ApigeeX\Entity\PrepaidBalanceInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\apigee_edge\SDKConnectorInterface;
use Drupal\apigee_m10n\Form\PrepaidBalanceConfigForm;
use Drupal\apigee_m10n\Form\PrepaidBalanceRefreshForm;
use Drupal\apigee_m10n\MonetizationInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Prepaid balance controller base.
*
* This is modeled after an entity list builder with some additions.
* See: `\Drupal\Core\Entity\EntityListBuilder`
*/
abstract class PrepaidBalanceXControllerBase extends ControllerBase implements PrepaidBalanceXControllerInterface {
/**
* The entity for this report.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
protected $entity;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* Apigee Monetization utility service.
*
* @var \Drupal\apigee_m10n\MonetizationInterface
*/
protected $monetization;
/**
* The Apigee SDK connector.
*
* @var \Drupal\apigee_edge\SDKConnectorInterface
*/
protected $sdk_connector;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Drupal core messenger service (for adding flash messages).
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* BillingController constructor.
*
* @param \Drupal\apigee_edge\SDKConnectorInterface $sdk_connector
* The `apigee_edge.sdk_connector` service.
* @param \Drupal\apigee_m10n\MonetizationInterface $monetization
* The `apigee_m10n.monetization` service.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* Drupal core messenger service (for adding flash messages).
*/
public function __construct(SDKConnectorInterface $sdk_connector, MonetizationInterface $monetization, FormBuilderInterface $form_builder, AccountInterface $current_user, ModuleHandlerInterface $module_handler, MessengerInterface $messenger) {
$this->sdk_connector = $sdk_connector;
$this->monetization = $monetization;
$this->currentUser = $current_user;
$this->formBuilder = $form_builder;
$this->moduleHandler = $module_handler;
$this->messenger = $messenger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('apigee_edge.sdk_connector'),
$container->get('apigee_m10n.monetization'),
$container->get('form_builder'),
$container->get('current_user'),
$container->get('module_handler'),
$container->get('messenger')
);
}
/**
* {@inheritdoc}
*/
public function render() {
// Sanitize the entity type for a type specific wrapper class.
$type_class = preg_replace('/[^a-z]+/', '-', $this->entity->getEntityTypeId());
$build = [
'#type' => 'container',
'#attributes' => [
'class' => ['apigee-m10n-prepaid-balance-wrapper', "apigee-m10n-{$type_class}-prepaid-balance-wrapper"],
],
'#attached' => [
'library' => [
'apigee_m10n/prepaid_balance',
],
],
];
// Add a refresh cache form.
if ($this->canRefreshBalance()) {
$build['refresh_form'] = $this->formBuilder()->getForm(PrepaidBalanceRefreshForm::class, $this->getCacheTags($this->entity));
}
$build['table'] = [
'#type' => 'table',
'#header' => $this->buildHeader(),
'#caption' => $this->getTitle(),
'#rows' => [],
'#empty' => $this->t('There are no balances available for this @label.', ['@label' => strtolower($this->entity->getEntityType()->getLabel())]),
'#cache' => [
'contexts' => ['url.path'],
'tags' => $this->getCacheTags($this->entity),
'max-age' => $max_age = $this->getCacheMaxAge(),
'keys' => [static::getCacheId($this->entity, 'prepaid_balances')],
],
];
// Convert wait time to miliseconds as the last credited time is miliseconds.
$wait_time_in_miliseconds = \Drupal::config('apigee_m10n_add_credit.general_settings.config')->get('wait_time') * 1000;
$utc = new \DateTimeZone('UTC');
$currentTimestamp = (new \DateTimeImmutable())->setTimezone($utc);
$currentTimestamp = ($currentTimestamp->getTimestamp() . $currentTimestamp->format('v'));
$time_to_wait = '';
foreach ($this->getDataFromCache($this->entity, 'prepaid_balances', [$this, 'load']) as $balance) {
/** @var \Apigee\Edge\Api\ApigeeX\Entity\PrepaidBalanceInterface $balance */
if ($row = $this->buildRow($balance)) {
$build['table']['#rows'][strtolower($balance->getBalance()->getCurrencyCode())] = $row;
$time_to_wait = $balance->getlastCreditTime() + $wait_time_in_miliseconds;
if ($time_to_wait > $currentTimestamp) {
$build['table']['#rows'][strtolower($balance->getBalance()->getCurrencyCode())]['#attributes']['class'] = 'disable-add-credit';
$seconds = floor(($time_to_wait - $currentTimestamp) / 1000);
$minutes = ((int) ($seconds / 60) % 60);
// If wait time set is less than 60 seconds, then the text is shown.
// minutes+1 is added to avoid showing seconds.
$minutes = ($wait_time_in_miliseconds <= 60000) ? "few seconds" : $minutes + 1 . ' mins';
$this->messenger->addWarning($this->t('**Add credit is disabled for @mins for currency @currency ', ['@mins' => $minutes, '@currency' => $balance->getBalance()->getCurrencyCode()]));
}
}
}
// Allow other modules to alter this build.
$this->moduleHandler->alter('apigee_m10n_prepaid_balance_list', $build, $this->entity);
return $build;
}
/**
* {@inheritdoc}
*/
public function getTitle() {
return $this->t('Current prepaid balance');
}
/**
* {@inheritdoc}
*/
public function buildHeader() {
return [
'currency' => $this->t('Account Currency'),
'current_balance' => $this->t('Current Balance'),
];
}
/**
* {@inheritdoc}
*/
public function buildRow(PrepaidBalanceInterface $balance) {
$currency_code = $balance->getBalance()->getCurrencyCode();
return [
'class' => ["apigee-balance-row-{$balance->getBalance()->getCurrencyCode()}"],
'data' => [
'currency' => $currency_code,
'current_balance' => $this->formatCurrency(($balance->getBalance()->getUnits() + $balance->getBalance()->getNanos()), $currency_code,),
],
];
}
/**
* Format an amount using the `monetization` service.
*
* See: \Drupal\apigee_m10n\MonetizationInterface::formatCurrency().
*
* @param string $amount
* The money amount.
* @param string $currency_code
* Currency code.
*
* @return string
* The formatted amount as a string.
*/
protected function formatCurrency($amount, $currency_code) {
return $this->monetization->formatCurrency($amount, $currency_code);
}
/**
* Helper to check if user has access to refresh prepaid balance.
*
* @return bool
* TRUE if user can refresh balance.
*/
abstract protected function canRefreshBalance();
/**
* Loads the balances for the listing.
*
* @return \Apigee\Edge\Api\ApigeeX\Entity\PrepaidBalanceInterface[]|array
* A list of apigee monetization prepaid balance entities.
*
* @throws \Exception
*/
abstract public function load();
/**
* Returns the cache max age.
*
* @return int
* The cache max age.
*/
protected function getCacheMaxAge() {
// Get the max-age from config.
if ($config = $this->config(PrepaidBalanceConfigForm::CONFIG_NAME)) {
return $config->get('cache.max_age');
}
return 0;
}
/**
* Helper to retrieve data from cache.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param string $suffix
* The cache id suffix.
* @param callable $callback
* The callback if not in cache.
*
* @return mixed
* The data.
*/
protected function getDataFromCache(EntityInterface $entity, string $suffix, callable $callback) {
$max_age = $this->getCacheMaxAge();
// If caching is disable, run callback and return.
if ($max_age == 0) {
return $callback();
}
$cid = $this->getCacheId($entity, $suffix);
// Check cache.
if ($cache = $this->cache()->get($cid)) {
return $cache->data;
}
$data = $callback();
$this->cache()
->set($cid, $data, time() + $max_age, $this->getCacheTags($entity));
return $data;
}
/**
* {@inheritdoc}
*/
public static function getCacheTags(EntityInterface $entity) {
return [
static::CACHE_MISS,
static::CACHE_PREFIX,
static::getCacheId($entity),
];
}
/**
* {@inheritdoc}
*/
public static function getCacheId(EntityInterface $entity, $suffix = NULL) {
return static::CACHE_PREFIX . ":{$entity->getEntityTypeId()}:{$entity->id()}" . ($suffix ? ":{$suffix}" : '');
}
}
