From 2c66fbd9920d0da65f5c63582760981e5288712e Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Mon, 3 Jul 2023 18:14:40 +0300 Subject: [PATCH 01/43] Refactored code realted to anonymous user token, moved to user info service --- .../quanthub_core/quanthub_core.services.yml | 4 +- .../src/AnonymousUserInfoTokenSubscriber.php | 112 +----------------- modules/quanthub_core/src/UserInfo.php | 99 +++++++++++++++- 3 files changed, 106 insertions(+), 109 deletions(-) diff --git a/modules/quanthub_core/quanthub_core.services.yml b/modules/quanthub_core/quanthub_core.services.yml index 6719224..56836df 100644 --- a/modules/quanthub_core/quanthub_core.services.yml +++ b/modules/quanthub_core/quanthub_core.services.yml @@ -31,7 +31,7 @@ services: class: '\Drupal\quanthub_core\AnonymousUserInfoTokenSubscriber' tags: - { name: event_subscriber } - arguments: ['@cache.default', '@current_user', '@logger.channel.quanthub_core', '@config.factory', '@http_client'] + arguments: ['@user_info'] # Event subscriber for getting and storing user info attributes for authenticated user. user_info_attributes_subscriber: @@ -43,7 +43,7 @@ services: # Get user info token for any user. user_info: class: '\Drupal\quanthub_core\UserInfo' - arguments: ['@current_user', '@cache.default', '@oidc.openid_connect_session', '@user.data', '@http_client'] + arguments: ['@current_user', '@cache.default', '@oidc.openid_connect_session', '@user.data', '@http_client', '@logger.channel.quanthub_core', '@config.factory'] powerbi_embed_configs: class: Drupal\quanthub_core\PowerBIEmbedConfigs diff --git a/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php b/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php index 7eb9c06..fa01e7f 100644 --- a/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php +++ b/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php @@ -2,12 +2,6 @@ namespace Drupal\quanthub_core; -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Session\AccountInterface; -use GuzzleHttp\ClientInterface; -use GuzzleHttp\Exception\RequestException; -use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; @@ -20,116 +14,22 @@ class AnonymousUserInfoTokenSubscriber implements EventSubscriberInterface, User /** * The config factory service. * - * @var \Drupal\Core\Config\ConfigFactoryInterface + * @var \Drupal\quanthub_core\UserInfo */ - protected $configFactory; - - /** - * The logger service. - * - * @var \Psr\Log\LoggerInterface - */ - protected $logger; - - /** - * The cache default service. - * - * @var \Drupal\Core\Cache\CacheBackendInterface - */ - protected $cache; - - /** - * The current user service. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $currentUser; - - /** - * The http client service. - * - * @var \GuzzleHttp\ClientInterface - */ - protected $httpClient; + protected $userInfo; /** * Constructs an AnonymousUserInfoTokenSubscriber object. */ - public function __construct(CacheBackendInterface $cache, AccountInterface $current_user, LoggerInterface $logger, ConfigFactoryInterface $configFactory, ClientInterface $http_client) { - $this->cache = $cache; - $this->currentUser = $current_user; - $this->logger = $logger; - $this->configFactory = $configFactory; - $this->httpClient = $http_client; + public function __construct(UserInfo $user_info) { + $this->userInfo = $user_info; } /** - * Get anonymous user info token and save to cache. - * - * As this token for anonymous user no sense to store this more secure. + * Check that token is existed. */ public function onRequest(RequestEvent $event) { - if ($this->currentUser->isAnonymous() || $this->currentUser->id() == 1) { - if (!$this->cache->get(self::ANONYMOUS_TOKEN_CID)) { - // Oidc plugin id is dynamic hash, we firstly get id from oidc settings. - $generic_realms = $this->configFactory->get('oidc.settings')->get('generic_realms'); - if (count($generic_realms) == 0) { - return; - } - - $oidc_plugin_id = array_shift($generic_realms); - $oidc_plugin = $this->configFactory->get('oidc.realm.quanthub_b2c_realm.' . $oidc_plugin_id); - if (!isset($oidc_plugin)) { - return; - } - $anonymous_endpoint = $oidc_plugin->get(self::ANONYMOUS_TOKEN_ENDPOINT); - - if ($anonymous_endpoint) { - try { - $response = $this->httpClient->get($anonymous_endpoint, [ - 'headers' => [ - 'Content-Type' => 'application/json', - ], - ]); - - $user_info_data = json_decode($response->getBody(), TRUE); - $this->cache->set(self::ANONYMOUS_TOKEN_CID, $user_info_data['token'], strtotime($user_info_data['expiresOn'])); - } - catch (RequestException $e) { - $this->logger->error('Failed to retrieve tokens for anonymous user: @error.', [ - '@error' => $e->getMessage(), - ]); - - throw new \RuntimeException('Failed to retrieve the user info anonymous token', 0, $e); - } - } - else { - $this->logger->error('Failed to retrieve tokens for anonymous user: Anonymous token is not set'); - } - - $user_attributes_endpoint = $oidc_plugin->get(self::USER_ATTRIBUTES_ENDPOINT); - if (!$this->cache->get(self::ANONYMOUS_QUANTHUB_USER_ID)) { - try { - $response = $this->httpClient->get($user_attributes_endpoint, [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $user_info_data['token'], - 'Content-Type' => 'application/json', - ], - ]); - - $user_attributes_data = json_decode($response->getBody(), TRUE); - $this->cache->set(self::ANONYMOUS_QUANTHUB_USER_ID, $user_attributes_data['userAttributes']['USER_ID'], strtotime($user_info_data['expiresOn'])); - } - catch (RequestException $e) { - $this->logger->error('Failed to retrieve quanthub user id for anonymous user: @error.', [ - '@error' => $e->getMessage(), - ]); - - throw new \RuntimeException('Failed to retrieve quanthub user id for anonymous token', 0, $e); - } - } - } - } + $this->userInfo->getToken(); } /** diff --git a/modules/quanthub_core/src/UserInfo.php b/modules/quanthub_core/src/UserInfo.php index 58057b5..ae09914 100644 --- a/modules/quanthub_core/src/UserInfo.php +++ b/modules/quanthub_core/src/UserInfo.php @@ -6,6 +6,11 @@ use Drupal\Core\Session\AccountInterface; use Drupal\oidc\OpenidConnectSessionInterface; use Drupal\user\UserDataInterface; +use GuzzleHttp\Exception\RequestException; +use Drupal\Core\Config\ConfigFactoryInterface; +use RuntimeException; +use GuzzleHttp\ClientInterface; +use Psr\Log\LoggerInterface; /** * The service for getting user info token and user attributes. @@ -42,14 +47,38 @@ class UserInfo implements UserInfoInterface { */ protected $userData; + /** + * The http client service. + * + * @var \GuzzleHttp\ClientInterface + */ + protected $httpClient; + + /** + * The logger service. + * + * @var \Psr\Log\LoggerInterface + */ + protected $logger; + + /** + * The logger service. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; + /** * Constructs an AnonymousUserInfoTokenSubscriber object. */ - public function __construct(AccountInterface $current_user, CacheBackendInterface $cache, OpenidConnectSessionInterface $openid_connect_session, UserDataInterface $user_data) { + public function __construct(AccountInterface $current_user, CacheBackendInterface $cache, OpenidConnectSessionInterface $openid_connect_session, UserDataInterface $user_data, ClientInterface $http_client, LoggerInterface $logger, ConfigFactoryInterface $configFactory) { $this->currentUser = $current_user; $this->cache = $cache; $this->openidConnectSession = $openid_connect_session; $this->userData = $user_data; + $this->httpClient = $http_client; + $this->logger = $logger; + $this->configFactory = $configFactory; } /** @@ -58,6 +87,9 @@ public function __construct(AccountInterface $current_user, CacheBackendInterfac public function getToken() { // For anonymous and admin we will use anonymous token. if ($this->currentUser->isAnonymous() || $this->currentUser->id() == 1) { + if (!$this->cache->get(self::ANONYMOUS_TOKEN_CID)) { + $this->updateAnonymousToken(); + } $token = $this->cache->get(self::ANONYMOUS_TOKEN_CID)->data; } else { @@ -116,4 +148,69 @@ public function getUserInfoGroups() { } } + /** + * Update user info anonymous token and save to the cache. + * + * As this token for anonymous user no sense to store this more secure. + */ + public function updateAnonymousToken() { + // Oidc plugin id is dynamic hash, we firstly get id from oidc settings. + $generic_realms = $this->configFactory->get('oidc.settings')->get('generic_realms'); + if (count($generic_realms) == 0) { + return; + } + + $oidc_plugin_id = array_shift($generic_realms); + $oidc_plugin = $this->configFactory->get('oidc.realm.quanthub_b2c_realm.' . $oidc_plugin_id); + if (!isset($oidc_plugin)) { + return; + } + $anonymous_endpoint = $oidc_plugin->get(self::ANONYMOUS_TOKEN_ENDPOINT); + + if ($anonymous_endpoint) { + try { + $response = $this->httpClient->get($anonymous_endpoint, [ + 'headers' => [ + 'Content-Type' => 'application/json', + ], + ]); + + $user_info_data = json_decode($response->getBody(), TRUE); + $this->cache->set(self::ANONYMOUS_TOKEN_CID, $user_info_data['token'], strtotime($user_info_data['expiresOn'])); + } + catch (RequestException $e) { + $this->logger->error('Failed to retrieve tokens for anonymous user: @error.', [ + '@error' => $e->getMessage(), + ]); + + throw new RuntimeException('Failed to retrieve the user info anonymous token', 0, $e); + } + } + else { + $this->logger->error('Failed to retrieve tokens for anonymous user: Anonymous token is not set'); + } + + $user_attributes_endpoint = $oidc_plugin->get(self::USER_ATTRIBUTES_ENDPOINT); + if (!$this->cache->get(self::ANONYMOUS_QUANTHUB_USER_ID) && !empty($user_info_data['token']) && !empty($user_info_data['expiresOn'])) { + try { + $response = $this->httpClient->get($user_attributes_endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $user_info_data['token'], + 'Content-Type' => 'application/json', + ], + ]); + + $user_attributes_data = json_decode($response->getBody(), TRUE); + $this->cache->set(self::ANONYMOUS_QUANTHUB_USER_ID, $user_attributes_data['userAttributes']['USER_ID'], strtotime($user_info_data['expiresOn'])); + } + catch (RequestException $e) { + $this->logger->error('Failed to retrieve quanthub user id for anonymous user: @error.', [ + '@error' => $e->getMessage(), + ]); + + throw new RuntimeException('Failed to retrieve quanthub user id for anonymous token', 0, $e); + } + } + } + } From 171e84c99385bec7ee848d8a1c1cccecc5a9f6f7 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Mon, 3 Jul 2023 18:18:21 +0300 Subject: [PATCH 02/43] Corrected code standards --- modules/quanthub_core/src/UserInfo.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/quanthub_core/src/UserInfo.php b/modules/quanthub_core/src/UserInfo.php index ae09914..e5062e9 100644 --- a/modules/quanthub_core/src/UserInfo.php +++ b/modules/quanthub_core/src/UserInfo.php @@ -3,12 +3,11 @@ namespace Drupal\quanthub_core; use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Session\AccountInterface; use Drupal\oidc\OpenidConnectSessionInterface; use Drupal\user\UserDataInterface; use GuzzleHttp\Exception\RequestException; -use Drupal\Core\Config\ConfigFactoryInterface; -use RuntimeException; use GuzzleHttp\ClientInterface; use Psr\Log\LoggerInterface; @@ -183,7 +182,7 @@ public function updateAnonymousToken() { '@error' => $e->getMessage(), ]); - throw new RuntimeException('Failed to retrieve the user info anonymous token', 0, $e); + throw new \RuntimeException('Failed to retrieve the user info anonymous token', 0, $e); } } else { @@ -208,7 +207,7 @@ public function updateAnonymousToken() { '@error' => $e->getMessage(), ]); - throw new RuntimeException('Failed to retrieve quanthub user id for anonymous token', 0, $e); + throw new \RuntimeException('Failed to retrieve quanthub user id for anonymous token', 0, $e); } } } From 0991dbd6c167bcc02c9b46514606672ffcbb793e Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Mon, 3 Jul 2023 18:19:37 +0300 Subject: [PATCH 03/43] Corrected code standards --- modules/quanthub_core/src/UserInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quanthub_core/src/UserInfo.php b/modules/quanthub_core/src/UserInfo.php index e5062e9..5ee264b 100644 --- a/modules/quanthub_core/src/UserInfo.php +++ b/modules/quanthub_core/src/UserInfo.php @@ -3,12 +3,12 @@ namespace Drupal\quanthub_core; use Drupal\Core\Cache\CacheBackendInterface; +use GuzzleHttp\ClientInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Session\AccountInterface; use Drupal\oidc\OpenidConnectSessionInterface; use Drupal\user\UserDataInterface; use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\ClientInterface; use Psr\Log\LoggerInterface; /** From 733ce310c06225c6c89246939f9b5056499c339a Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Mon, 3 Jul 2023 18:32:26 +0300 Subject: [PATCH 04/43] Corrected code standards --- modules/quanthub_core/src/UserInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quanthub_core/src/UserInfo.php b/modules/quanthub_core/src/UserInfo.php index 5ee264b..f2fa203 100644 --- a/modules/quanthub_core/src/UserInfo.php +++ b/modules/quanthub_core/src/UserInfo.php @@ -3,11 +3,11 @@ namespace Drupal\quanthub_core; use Drupal\Core\Cache\CacheBackendInterface; -use GuzzleHttp\ClientInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Session\AccountInterface; use Drupal\oidc\OpenidConnectSessionInterface; use Drupal\user\UserDataInterface; +use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\RequestException; use Psr\Log\LoggerInterface; From 7934c380c3ac6a9f387393c2bd3480cf7db56e45 Mon Sep 17 00:00:00 2001 From: Oleksandr Tiupa Date: Tue, 11 Jul 2023 11:33:01 +0300 Subject: [PATCH 05/43] created a processor for rewriting calendar event color based on the release type --- .../ReleaseTypeProcessor.php | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php diff --git a/modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php b/modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php new file mode 100644 index 0000000..0ef30e4 --- /dev/null +++ b/modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php @@ -0,0 +1,49 @@ +result as $key => $row) { + $current_entity = $row->_entity; + $release_type = $current_entity->get('field_release_type')->value; + if (!empty($entries[$key])) { + $entries[$key]['backgroundColor'] = match($release_type) { + 'dataset' => '#A1ECC7', + 'press_release' => '#C6DCEC', + default => '#C6DCED' + }; + } + } + // Update the entries. + if ($entries) { + $calendar_options['events'] = $entries; + $variables['#attached']['drupalSettings']['fullCalendarView'][$view_index]['calendar_options'] = json_encode($calendar_options); + } + } + +} From e4984e8dbc2196c63093d0fb84d2a71be8afdf22 Mon Sep 17 00:00:00 2001 From: Oleksandr Tiupa Date: Tue, 11 Jul 2023 11:51:24 +0300 Subject: [PATCH 06/43] added todo --- .../Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php b/modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php index 0ef30e4..14008f4 100644 --- a/modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php +++ b/modules/quanthub_core/src/Plugin/FullcalendarViewProcessor/ReleaseTypeProcessor.php @@ -33,6 +33,7 @@ public function process(array &$variables) { $release_type = $current_entity->get('field_release_type')->value; if (!empty($entries[$key])) { $entries[$key]['backgroundColor'] = match($release_type) { + // @todo Set colors from the UI. 'dataset' => '#A1ECC7', 'press_release' => '#C6DCEC', default => '#C6DCED' From 3ac44ace159c92b2862333c84829d98ebbb06f32 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Tue, 11 Jul 2023 20:31:22 +0300 Subject: [PATCH 07/43] Implemented first version of gauges service for syncing data between SDMX and Drupal gauges node, also added template for guages --- .../quanthub_sdmx_sync.module | 2 +- .../quanthub_sdmx_sync.services.yml | 8 +- .../src/QuanthubSdmxClient.php | 32 ++++ .../src/QuanthubSdmxSyncGauges.php | 150 +++++++++++++++++- .../content/node--gauge--details.html.twig | 98 ++++++++++++ 5 files changed, 280 insertions(+), 10 deletions(-) create mode 100644 themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig diff --git a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module index c1d1913..430323a 100644 --- a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module +++ b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module @@ -9,7 +9,7 @@ * Cron callback for running service sdxm sync gauges. */ function quanthub_sdmx_sync_gauges_cron() { - + \Drupal::service('sdmx_sync_gauges')->syncGauages(); } /** diff --git a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.services.yml b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.services.yml index 6060b88..292bd4f 100644 --- a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.services.yml +++ b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.services.yml @@ -8,9 +8,7 @@ services: sdmx_sync_datasets: class: Drupal\quanthub_sdmx_sync\QuanthubSdmxSyncDatasets arguments: ['@sdmx_client', '@entity_type.manager', '@database'] - - -# sdmx_sync_gauges: -# class: Drupal\quanthub_sdmx_sync\SdmxSyncGauges -# arguments: [] + sdmx_sync_gauges: + class: Drupal\quanthub_sdmx_sync\QuanthubSdmxSyncGauges + arguments: ['@sdmx_client', '@entity_type.manager', '@database'] diff --git a/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php b/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php index d3bae31..af87a05 100644 --- a/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php +++ b/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php @@ -91,4 +91,36 @@ public function getDasetStructure(string $urn_for_url) { } } + /** + * Get dataset filtered data by method GET. + * + * @param string $urn_for_url + * The dataset urn for url. + * @param string $filters + * The filters string divided by dot. + * + * @return mixed|void + * The decoded response from SDMX. + */ + public function getDatasetFilteredData(string $urn_for_url, string $filters) { + $baseUri = getenv('SDMX_API_URL') . '/workspaces/' . getenv('SDMX_WORKSPACE_ID') . '/registry/sdmx/3.0/data/dataflow/'; + + $guzzleClient = $this->httpClientFactory->fromOptions([ + 'base_uri' => $baseUri, + 'headers' => $this->headers, + ]); + + try { + return json_decode( + $guzzleClient->get($urn_for_url . '/' . $filters)->getBody(), + TRUE + ); + } + catch (\Exception $e) { + $this->logger->error('Failed to retrieve tokens for anonymous user: @error.', [ + '@error' => $e->getMessage(), + ]); + } + } + } diff --git a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php index f21319c..e69933c 100644 --- a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php +++ b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php @@ -1,12 +1,154 @@ sdmxClient = $sdmx_client; + $this->entityTypeManager = $entity_type_manager; + $this->gaugesStorage = $this->entityTypeManager->getStorage(self::GAUGES_ENTITY_TYPE); + $this->database = $database; + } + + /** + * Get published gauges. + */ + public function getGaugesData() { + $query = $this->database->select('node_field_data', 'n'); + $query->condition('n.type', self::GAUGES_ENTITY_BUNDLE); + $query->condition('n.status', 1); + $query->join('node__field_dataset', 'nfd', 'nfd.entity_id = n.nid'); + $query->join('node__field_quanthub_urn', 'nfqu', 'nfqu.entity_id = nfd.field_dataset_target_id'); + $query->join('node__field_gauge_filter', 'nfqf', 'nfqf.entity_id = n.nid'); + $query->addField('n', 'nid'); + $query->addField('nfqf', 'field_gauge_filter_value', 'filter'); + $query->addField('nfqu', 'field_quanthub_urn_value', 'quanthub_urn'); + return $query->execute()->fetchAll(); + } + + /** + * Sync gauges data. + */ + public function syncGauages() { + $gauges_data = $this->getGaugesData(); + foreach ($gauges_data as $gauge_data) { + $dataset_data = $this->sdmxClient->getDatasetFilteredData( + $this->transformUrn( + $gauge_data->quanthub_urn + ), + $gauge_data->filter + ); + + if ( + !empty($dataset_data['data']['dataSets'][0]['series']) && + !empty($dataset_data['data']['structures'][0]['dimensions']['observation'][0]['values']) + ) { + $structure_observation = $dataset_data['data']['structures'][0]['dimensions']['observation'][0]['values']; + $last_structure_observation = end($structure_observation)['value']; + + $structure_series = $dataset_data['data']['dataSets'][0]['series']; + $structure_observations = array_column($structure_series, 'observations'); + $structure_observations = end($structure_observations); + $last_serie_value = end($structure_observations); + $last_serie_value = end($last_serie_value); + $this->updateGauge( + $gauge_data->nid, + $last_structure_observation, + $last_serie_value + ); + } + } + } + + /** + * Transform dataset urn for using in api request. + * + * @param string $dataset_urn + * The dataset urn string. + * + * @return string + * Transformed dataset urn string. + */ + public function transformUrn(string $dataset_urn): string { + // @todo need refactor and move to other space perhaps trait. + // Changed divider in string to slash for url if found version. + if (preg_match("/\([0-9.]/", $dataset_urn)) { + $dataset_urn_url = str_replace([':', '('], '/', $dataset_urn); + $dataset_urn_url = str_replace(')', '', $dataset_urn_url); + } + else { + // We need latest dataset version, if version isn't specified. + $dataset_urn_url = str_replace('(*)', '/latest', $dataset_urn); + } + + return $dataset_urn_url; + } + + /** + * Update gauge node. + * + * @param int $nid + * The node id. + * @param string $period + * The period. + * @param string $value + * The value. + */ + public function updateGauge(int $nid, string $period, string $value) { + $entity = $this->entityTypeManager->getStorage('node')->load($nid); + + $entity->set('field_gauge_period', $period); + $entity->set('field_gauge_value', $value); + + $entity->save(); + } + } diff --git a/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig new file mode 100644 index 0000000..8ac869e --- /dev/null +++ b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig @@ -0,0 +1,98 @@ +{# +/** + * @file + * Theme override to display a node. + * + * Available variables: + * - node: The node entity with limited access to object properties and methods. + * Only method names starting with "get", "has", or "is" and a few common + * methods such as "id", "label", and "bundle" are available. For example: + * - node.getCreatedTime() will return the node creation timestamp. + * - node.hasField('field_example') returns TRUE if the node bundle includes + * field_example. (This does not indicate the presence of a value in this + * field.) + * - node.isPublished() will return whether the node is published or not. + * Calling other methods, such as node.delete(), will result in an exception. + * See \Drupal\node\Entity\Node for a full list of public properties and + * methods for the node object. + * - label: (optional) The title of the node. + * - content: All node items. Use {{ content }} to print them all, + * or print a subset such as {{ content.field_example }}. Use + * {{ content|without('field_example') }} to temporarily suppress the printing + * of a given child element. + * - author_picture: The node author user entity, rendered using the "compact" + * view mode. + * - metadata: Metadata for this node. + * - date: (optional) Themed creation date field. + * - author_name: (optional) Themed author name field. + * - url: Direct URL of the current node. + * - display_submitted: Whether submission information should be displayed. + * - attributes: HTML attributes for the containing element. + * The attributes.class element may contain one or more of the following + * classes: + * - node: The current template type (also known as a "theming hook"). + * - node--type-[type]: The current node type. For example, if the node is an + * "Article" it would result in "node--type-article". Note that the machine + * name will often be in a short form of the human readable label. + * - node--view-mode-[view_mode]: The View Mode of the node; for example, a + * teaser would result in: "node--view-mode-teaser", and + * full: "node--view-mode-full". + * The following are controlled through the node publishing options. + * - node--promoted: Appears on nodes promoted to the front page. + * - node--sticky: Appears on nodes ordered above other non-sticky nodes in + * teaser listings. + * - node--unpublished: Appears on unpublished nodes visible only to site + * admins. + * - title_attributes: Same as attributes, except applied to the main title + * tag that appears in the template. + * - content_attributes: Same as attributes, except applied to the main + * content tag that appears in the template. + * - author_attributes: Same as attributes, except applied to the author of + * the node tag that appears in the template. + * - title_prefix: Additional output populated by modules, intended to be + * displayed in front of the main title tag that appears in the template. + * - title_suffix: Additional output populated by modules, intended to be + * displayed after the main title tag that appears in the template. + * - view_mode: View mode; for example, "teaser" or "full". + * - teaser: Flag for the teaser state. Will be true if view_mode is 'teaser'. + * - page: Flag for the full page state. Will be true if view_mode is 'full'. + * - readmore: Flag for more state. Will be true if the teaser content of the + * node cannot hold the main body content. + * - logged_in: Flag for authenticated user status. Will be true when the + * current user is a logged-in member. + * - is_admin: Flag for admin user status. Will be true when the current user + * is an administrator. + * + * @see template_preprocess_node() + * + */ +#} + + +
+
+ + {{ label }} + +
+
+ + {% if node.field_gauge_scale is empty %} + {{ node.field_gauge_value.value|round(2) }} + {% else %} + {{ (node.field_gauge_value.value / node.field_gauge_scale.value)|round(2) }} + {% endif %} + {% if node.field_gauge_unit_of_measure is not empty %} + {{ node.field_gauge_unit_of_measure.value }} + {% endif %} + +
+ +
+
From 169546bae0152c205f2a41f7e9efc25d40a08972 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Wed, 12 Jul 2023 16:51:22 +0300 Subject: [PATCH 08/43] Added improvments to SDMX client, refactored services for syncing datasets and gauges --- .../src/QuanthubSdmxClient.php | 41 ++++++++++++++++--- .../src/QuanthubSdmxSyncDatasets.php | 25 +---------- .../src/QuanthubSdmxSyncGauges.php | 28 +------------ 3 files changed, 37 insertions(+), 57 deletions(-) diff --git a/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php b/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php index af87a05..216eca0 100644 --- a/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php +++ b/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php @@ -63,13 +63,13 @@ public function __construct(ClientFactory $http_client_factory, UserInfo $user_i /** * The get request to SDMX api. * - * @param string $urn_for_url - * The dataset urn for url. + * @param string $urn + * The dataset urn. * * @return array * The response body array decoded json. */ - public function getDasetStructure(string $urn_for_url) { + public function getDasetStructure(string $urn) { $baseUri = getenv('SDMX_API_URL') . '/workspaces/' . getenv('SDMX_WORKSPACE_ID') . '/registry/sdmx-plus/structure/dataflow/'; $guzzleClient = $this->httpClientFactory->fromOptions([ @@ -81,6 +81,8 @@ public function getDasetStructure(string $urn_for_url) { ], ]); + $urn_for_url = $this->transformUrn($urn); + try { return json_decode($guzzleClient->get($urn_for_url)->getBody(), TRUE); } @@ -94,15 +96,15 @@ public function getDasetStructure(string $urn_for_url) { /** * Get dataset filtered data by method GET. * - * @param string $urn_for_url - * The dataset urn for url. + * @param string $urn + * The dataset urn. * @param string $filters * The filters string divided by dot. * * @return mixed|void * The decoded response from SDMX. */ - public function getDatasetFilteredData(string $urn_for_url, string $filters) { + public function getDatasetFilteredData(string $urn, string $filters) { $baseUri = getenv('SDMX_API_URL') . '/workspaces/' . getenv('SDMX_WORKSPACE_ID') . '/registry/sdmx/3.0/data/dataflow/'; $guzzleClient = $this->httpClientFactory->fromOptions([ @@ -110,6 +112,8 @@ public function getDatasetFilteredData(string $urn_for_url, string $filters) { 'headers' => $this->headers, ]); + $urn_for_url = $this->transformUrn($urn); + try { return json_decode( $guzzleClient->get($urn_for_url . '/' . $filters)->getBody(), @@ -123,4 +127,29 @@ public function getDatasetFilteredData(string $urn_for_url, string $filters) { } } + /** + * Transform dataset urn for using in api request. + * + * @param string $dataset_urn + * The dataset urn string. + * + * @return string + * Transformed dataset urn string. + */ + public function transformUrn(string $dataset_urn): string { + // Change divider between agency and dataset id. + $dataset_urn_url = str_replace(':', '/', $dataset_urn); + // Transform versioning of dataset logic. + if (preg_match("/\([0-9.]/", $dataset_urn_url)) { + $dataset_urn_url = str_replace('(', '/', $dataset_urn_url); + $dataset_urn_url = str_replace(')', '', $dataset_urn_url); + } + else { + // We need latest dataset version, if version isn't specified. + $dataset_urn_url = str_replace('(*)', '/latest', $dataset_urn_url); + } + + return $dataset_urn_url; + } + } diff --git a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncDatasets.php b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncDatasets.php index 8be2de0..77b4a7a 100644 --- a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncDatasets.php +++ b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncDatasets.php @@ -87,7 +87,7 @@ public function syncDatasetsUpdateDate() { * Get last update date from sdmx for dataset by dataset urn. */ public function getDatasetUpdateDate($dataset_urn) { - $dataset_structure = $this->sdmxClient->getDasetStructure($this->transformUrn($dataset_urn)); + $dataset_structure = $this->sdmxClient->getDasetStructure($dataset_urn); if (!empty($dataset_structure['data']['dataflows'])) { $dataflow_data = $dataset_structure['data']['dataflows']; @@ -121,27 +121,4 @@ public function getDatasetUrns(): array { return $query->execute()->fetchAllKeyed(); } - /** - * Transform dataset urn for using in api request. - * - * @param string $dataset_urn - * The dataset urn string. - * - * @return string - * Transformed dataset urn string. - */ - public function transformUrn(string $dataset_urn): string { - // Changed divider in string to slash for url if found version. - if (preg_match("/\([0-9.]/", $dataset_urn)) { - $dataset_urn_url = str_replace([':', '('], '/', $dataset_urn); - $dataset_urn_url = str_replace(')', '', $dataset_urn_url); - } - else { - // We need latest dataset version, if version isn't specified. - $dataset_urn_url = str_replace('(*)', '/latest', $dataset_urn); - } - - return $dataset_urn_url; - } - } diff --git a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php index e69933c..9529c5d 100644 --- a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php +++ b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php @@ -81,9 +81,7 @@ public function syncGauages() { $gauges_data = $this->getGaugesData(); foreach ($gauges_data as $gauge_data) { $dataset_data = $this->sdmxClient->getDatasetFilteredData( - $this->transformUrn( - $gauge_data->quanthub_urn - ), + $gauge_data->quanthub_urn, $gauge_data->filter ); @@ -108,30 +106,6 @@ public function syncGauages() { } } - /** - * Transform dataset urn for using in api request. - * - * @param string $dataset_urn - * The dataset urn string. - * - * @return string - * Transformed dataset urn string. - */ - public function transformUrn(string $dataset_urn): string { - // @todo need refactor and move to other space perhaps trait. - // Changed divider in string to slash for url if found version. - if (preg_match("/\([0-9.]/", $dataset_urn)) { - $dataset_urn_url = str_replace([':', '('], '/', $dataset_urn); - $dataset_urn_url = str_replace(')', '', $dataset_urn_url); - } - else { - // We need latest dataset version, if version isn't specified. - $dataset_urn_url = str_replace('(*)', '/latest', $dataset_urn); - } - - return $dataset_urn_url; - } - /** * Update gauge node. * From 350c68aa1f0fc8c82d8ffe269689f4bf4285ec98 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:26:01 +0300 Subject: [PATCH 09/43] Update quanthub_tailwindcss.theme --- themes/quanthub_tailwindcss/quanthub_tailwindcss.theme | 2 ++ 1 file changed, 2 insertions(+) diff --git a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme index 1dd399d..6c0d79e 100644 --- a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme +++ b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme @@ -35,8 +35,10 @@ function quanthub_tailwindcss_get_active_theme() { function quanthub_tailwindcss_preprocess_page(array &$variables) { $workspaceId = getenv('SDMX_WORKSPACE_ID'); $defaultCategorySchemeUrn = getenv('SDMX_DEFAULT_CATEGORY_SCHEME_URN'); + $dataAttributeId = getenv('DATASET_EXPLORER_DATA_ATTRIBUTE_ID'); $variables['#attached']['drupalSettings']['workspaceId'] = $workspaceId; $variables['#attached']['drupalSettings']['defaultCategorySchemeUrn'] = $defaultCategorySchemeUrn; + $variables['#attached']['drupalSettings']['dataAttributeId'] = $dataAttributeId; } /** From e18bf31fa8db76a4adb47940b526fdee1f534387 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Wed, 19 Jul 2023 22:27:34 +0300 Subject: [PATCH 10/43] Added rounding for special numbers quantity after dot --- .../templates/content/node--gauge--details.html.twig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig index 8ac869e..0265f6d 100644 --- a/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig +++ b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig @@ -78,7 +78,11 @@
{% if node.field_gauge_scale is empty %} - {{ node.field_gauge_value.value|round(2) }} + {% if node.field_gauge_round_number is empty or node.field_gauge_round_number.value == 0 %} + {{ node.field_gauge_value.value }} + {% elseif node.field_gauge_round_number.value > 0 %} + {{ node.field_gauge_value.value|round(node.field_gauge_round_number.value) }} + {% endif %} {% else %} {{ (node.field_gauge_value.value / node.field_gauge_scale.value)|round(2) }} {% endif %} From 41290801c5eb981ceb38c55b0bbb3772f99e87a8 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Thu, 20 Jul 2023 14:32:38 +0300 Subject: [PATCH 11/43] Added form widget for better UI for scaling functionality --- .../FieldWidget/QuantHubScaleNumberWidget.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php diff --git a/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php new file mode 100644 index 0000000..628e31c --- /dev/null +++ b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php @@ -0,0 +1,42 @@ + '10', + 100 => '100', + 1000 => '1 000', + 1000000 => '1 000 000', + 1000000000 => '1 000 000 000', + ]; + + return $element; + } + +} From 26a85767afbad8dc175c6d2744e3e2cfd3e52ce5 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Thu, 20 Jul 2023 19:23:27 +0300 Subject: [PATCH 12/43] Refactored service for updating gauges, added functionality for updating gauges after update or insert, corrected widget for scaling better UI/UX --- .../FieldWidget/QuantHubScaleNumberWidget.php | 9 ++- .../quanthub_sdmx_sync.module | 34 +++++++++++ .../src/QuanthubSdmxSyncGauges.php | 56 +++++++++++++------ 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php index 628e31c..5f26d59 100644 --- a/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php +++ b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php @@ -29,11 +29,10 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $element['value']['#type'] = 'select'; $element['value']['#options'] = [ - 10 => '10', - 100 => '100', - 1000 => '1 000', - 1000000 => '1 000 000', - 1000000000 => '1 000 000 000', + 100 => $this->t('Hundreds'), + 1000 => $this->t('Thousands'), + 1000000 => $this->t('Millions'), + 1000000000 => $this->t('Billions'), ]; return $element; diff --git a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module index 430323a..4a8cff1 100644 --- a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module +++ b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module @@ -5,6 +5,8 @@ * Contains quanthub_sdmx_sync.module. */ +use Drupal\Core\Entity\EntityInterface; + /** * Cron callback for running service sdxm sync gauges. */ @@ -18,3 +20,35 @@ function quanthub_sdmx_sync_gauges_cron() { function quanthub_sdmx_sync_datasets_cron() { \Drupal::service('sdmx_sync_datasets')->syncDatasetsUpdateDate(); } + +/** + * Implements hook_ENTITY_TYPE_insert(). + */ +function quanthub_sdmx_sync_node_insert(EntityInterface $entity) { + _quanthub_sdmx_sync_guage_update_values($entity); +} + +/** + * Implements hook_ENTITY_TYPE_update(). + */ +function quanthub_sdmx_sync_node_update(EntityInterface $entity) { + _quanthub_sdmx_sync_guage_update_values($entity); +} + +/** + * Helper function for updating period and value from in gauge from sdmx client. + */ +function _quanthub_sdmx_sync_guage_update_values(EntityInterface &$entity) { + if ($entity->bundle() == 'gauge') { + $filter = $entity->field_gauge_filter->getString(); + $urn = $entity->field_dataset->entity->field_quanthub_urn->getString(); + $gauge_updates = \Drupal::service('sdmx_sync_gauges')->getGaugeLastValueAndObservation( + $urn, + $filter + ); + if ($gauge_updates) { + $entity->field_gauge_value->set($gauge_updates['last_serie_value']); + $entity->field_gauge_period->set($gauge_updates['last_structure_observation']); + } + } +} diff --git a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php index 9529c5d..82fa970 100644 --- a/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php +++ b/modules/quanthub_sdmx_sync/src/QuanthubSdmxSyncGauges.php @@ -61,7 +61,7 @@ public function __construct(QuanthubSdmxClient $sdmx_client, EntityTypeManager $ /** * Get published gauges. */ - public function getGaugesData() { + public function getPublishedGaugesData() { $query = $this->database->select('node_field_data', 'n'); $query->condition('n.type', self::GAUGES_ENTITY_BUNDLE); $query->condition('n.status', 1); @@ -78,34 +78,56 @@ public function getGaugesData() { * Sync gauges data. */ public function syncGauages() { - $gauges_data = $this->getGaugesData(); + $gauges_data = $this->getPublishedGaugesData(); foreach ($gauges_data as $gauge_data) { - $dataset_data = $this->sdmxClient->getDatasetFilteredData( + $gauge_updates = $this->getGaugeLastValueAndObservation( $gauge_data->quanthub_urn, $gauge_data->filter ); - if ( - !empty($dataset_data['data']['dataSets'][0]['series']) && - !empty($dataset_data['data']['structures'][0]['dimensions']['observation'][0]['values']) - ) { - $structure_observation = $dataset_data['data']['structures'][0]['dimensions']['observation'][0]['values']; - $last_structure_observation = end($structure_observation)['value']; - - $structure_series = $dataset_data['data']['dataSets'][0]['series']; - $structure_observations = array_column($structure_series, 'observations'); - $structure_observations = end($structure_observations); - $last_serie_value = end($structure_observations); - $last_serie_value = end($last_serie_value); + if ($gauge_updates) { $this->updateGauge( $gauge_data->nid, - $last_structure_observation, - $last_serie_value + $gauge_updates['last_structure_observation'], + $gauge_updates['last_serie_value'] ); } } } + /** + * Get Gauge last value and last structure observation. + * + * @param string $urn + * The quanthub urn string. + * @param string $filter + * The filter string. + * + * @return array|false + * The array of data or false. + */ + public function getGaugeLastValueAndObservation($urn, $filter) { + $dataset_data = $this->sdmxClient->getDatasetFilteredData($urn, $filter); + + if ( + !empty($dataset_data['data']['dataSets'][0]['series']) && + !empty($dataset_data['data']['structures'][0]['dimensions']['observation'][0]['values']) + ) { + $structure_observation = $dataset_data['data']['structures'][0]['dimensions']['observation'][0]['values']; + $last_structure_observation = end($structure_observation)['value']; + + $structure_series = $dataset_data['data']['dataSets'][0]['series']; + $structure_observations = array_column($structure_series, 'observations'); + $structure_observations = end($structure_observations); + $last_serie_value = end($structure_observations); + $last_serie_value = end($last_serie_value); + + return compact('last_serie_value', 'last_structure_observation'); + } + + return FALSE; + } + /** * Update gauge node. * From e8b0196d591e1a9519c8d91d8cc337d7aade4519 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Fri, 21 Jul 2023 11:10:34 +0300 Subject: [PATCH 13/43] Fixed error with saving gauges --- modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module index 4a8cff1..f432a40 100644 --- a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module +++ b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module @@ -47,8 +47,8 @@ function _quanthub_sdmx_sync_guage_update_values(EntityInterface &$entity) { $filter ); if ($gauge_updates) { - $entity->field_gauge_value->set($gauge_updates['last_serie_value']); - $entity->field_gauge_period->set($gauge_updates['last_structure_observation']); + $entity->set('field_gauge_value', $gauge_updates['last_serie_value']); + $entity->set('field_gauge_period', $gauge_updates['last_structure_observation']); } } } From b5d426e3accb2c07a588a693b15b806d0b6fa82f Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Fri, 21 Jul 2023 13:06:04 +0300 Subject: [PATCH 14/43] Added fixes for updating gauge and for template, added no scaling to form --- .../FieldWidget/QuantHubScaleNumberWidget.php | 1 + .../quanthub_sdmx_sync.module | 18 ++--------------- .../content/node--gauge--details.html.twig | 20 ++++++++++++------- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php index 5f26d59..8013606 100644 --- a/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php +++ b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php @@ -34,6 +34,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen 1000000 => $this->t('Millions'), 1000000000 => $this->t('Billions'), ]; + $element['value']['#empty_option'] = $this->t('No scaling'); return $element; } diff --git a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module index f432a40..ae6cdf8 100644 --- a/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module +++ b/modules/quanthub_sdmx_sync/quanthub_sdmx_sync.module @@ -22,23 +22,9 @@ function quanthub_sdmx_sync_datasets_cron() { } /** - * Implements hook_ENTITY_TYPE_insert(). + * Implements hook_ENTITY_TYPE_presave(). */ -function quanthub_sdmx_sync_node_insert(EntityInterface $entity) { - _quanthub_sdmx_sync_guage_update_values($entity); -} - -/** - * Implements hook_ENTITY_TYPE_update(). - */ -function quanthub_sdmx_sync_node_update(EntityInterface $entity) { - _quanthub_sdmx_sync_guage_update_values($entity); -} - -/** - * Helper function for updating period and value from in gauge from sdmx client. - */ -function _quanthub_sdmx_sync_guage_update_values(EntityInterface &$entity) { +function quanthub_sdmx_sync_node_presave(EntityInterface $entity) { if ($entity->bundle() == 'gauge') { $filter = $entity->field_gauge_filter->getString(); $urn = $entity->field_dataset->entity->field_quanthub_urn->getString(); diff --git a/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig index 0265f6d..c82cb78 100644 --- a/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig +++ b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig @@ -77,14 +77,20 @@
- {% if node.field_gauge_scale is empty %} - {% if node.field_gauge_round_number is empty or node.field_gauge_round_number.value == 0 %} - {{ node.field_gauge_value.value }} - {% elseif node.field_gauge_round_number.value > 0 %} - {{ node.field_gauge_value.value|round(node.field_gauge_round_number.value) }} + {% if node.field_gauge_value is not empty %} + {% if node.field_gauge_scale is empty %} + {% if node.field_gauge_round_number is empty or node.field_gauge_round_number.value == 0 %} + {{ node.field_gauge_value.value }} + {% else %} + {{ node.field_gauge_value.value|round(node.field_gauge_round_number.value) }} + {% endif %} + {% else %} + {% if node.field_gauge_round_number is empty or node.field_gauge_round_number.value == 0 %} + {{ (node.field_gauge_value.value / node.field_gauge_scale.value) }} + {% else %} + {{ (node.field_gauge_value.value / node.field_gauge_scale.value)|round(node.field_gauge_round_number.value) }} + {% endif %} {% endif %} - {% else %} - {{ (node.field_gauge_value.value / node.field_gauge_scale.value)|round(2) }} {% endif %} {% if node.field_gauge_unit_of_measure is not empty %} {{ node.field_gauge_unit_of_measure.value }} From ef754fe368aadcb3117fbc2c6ea165c1e527041d Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Fri, 21 Jul 2023 16:03:08 +0300 Subject: [PATCH 15/43] Corrected logging messages --- modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php b/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php index 216eca0..c65843c 100644 --- a/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php +++ b/modules/quanthub_sdmx_sync/src/QuanthubSdmxClient.php @@ -87,7 +87,7 @@ public function getDasetStructure(string $urn) { return json_decode($guzzleClient->get($urn_for_url)->getBody(), TRUE); } catch (\Exception $e) { - $this->logger->error('Failed to retrieve tokens for anonymous user: @error.', [ + $this->logger->error('Failed to retrieve dataset structure: @error.', [ '@error' => $e->getMessage(), ]); } @@ -121,7 +121,7 @@ public function getDatasetFilteredData(string $urn, string $filters) { ); } catch (\Exception $e) { - $this->logger->error('Failed to retrieve tokens for anonymous user: @error.', [ + $this->logger->error('Failed to retrieve filtered dataset data: @error.', [ '@error' => $e->getMessage(), ]); } From 0210fa5c6c41f77d64cc5d2180246135fda00285 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Tue, 25 Jul 2023 09:33:28 +0300 Subject: [PATCH 16/43] Feature: support unitsOfMeasureId --- themes/quanthub_tailwindcss/quanthub_tailwindcss.theme | 2 ++ 1 file changed, 2 insertions(+) diff --git a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme index 6c0d79e..80dbb0f 100644 --- a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme +++ b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme @@ -36,9 +36,11 @@ function quanthub_tailwindcss_preprocess_page(array &$variables) { $workspaceId = getenv('SDMX_WORKSPACE_ID'); $defaultCategorySchemeUrn = getenv('SDMX_DEFAULT_CATEGORY_SCHEME_URN'); $dataAttributeId = getenv('DATASET_EXPLORER_DATA_ATTRIBUTE_ID'); + $unitsOfMeasureId = getenv('UNITS_OF_MEASURE_ATTRIBUTE_ID'); $variables['#attached']['drupalSettings']['workspaceId'] = $workspaceId; $variables['#attached']['drupalSettings']['defaultCategorySchemeUrn'] = $defaultCategorySchemeUrn; $variables['#attached']['drupalSettings']['dataAttributeId'] = $dataAttributeId; + $variables['#attached']['drupalSettings']['unitsOfMeasureId'] = $unitsOfMeasureId; } /** From d056de76e620cede066d629032f962f95f5a927a Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Tue, 25 Jul 2023 14:38:01 +0300 Subject: [PATCH 17/43] Update quanthub_tailwindcss.theme --- themes/quanthub_tailwindcss/quanthub_tailwindcss.theme | 2 ++ 1 file changed, 2 insertions(+) diff --git a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme index 80dbb0f..deabe8e 100644 --- a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme +++ b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme @@ -34,10 +34,12 @@ function quanthub_tailwindcss_get_active_theme() { */ function quanthub_tailwindcss_preprocess_page(array &$variables) { $workspaceId = getenv('SDMX_WORKSPACE_ID'); + $defaultDataset = getenv('SDMX_DEFAULT_DATASET'); $defaultCategorySchemeUrn = getenv('SDMX_DEFAULT_CATEGORY_SCHEME_URN'); $dataAttributeId = getenv('DATASET_EXPLORER_DATA_ATTRIBUTE_ID'); $unitsOfMeasureId = getenv('UNITS_OF_MEASURE_ATTRIBUTE_ID'); $variables['#attached']['drupalSettings']['workspaceId'] = $workspaceId; + $variables['#attached']['drupalSettings']['defaultDataset'] = $defaultDataset; $variables['#attached']['drupalSettings']['defaultCategorySchemeUrn'] = $defaultCategorySchemeUrn; $variables['#attached']['drupalSettings']['dataAttributeId'] = $dataAttributeId; $variables['#attached']['drupalSettings']['unitsOfMeasureId'] = $unitsOfMeasureId; From ba476b7eb81ef925ddc858c23b47c67ba2fb1254 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:48:08 +0300 Subject: [PATCH 18/43] Update quanthub_sdmx_proxy.routing.yml --- .../quanthub_sdmx_proxy.routing.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml b/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml index d349214..c176d8e 100644 --- a/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml +++ b/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml @@ -13,4 +13,13 @@ sdmx_proxy.forwarder: _controller: Drupal\quanthub_sdmx_proxy\Controller\Forwarder::forward _title: 'SDMX API Proxy request forwarder' requirements: - _permission: 'access content' \ No newline at end of file + _permission: 'access content' + +sdmx_proxy.forwarder-download: + path: '/sdmx-download' + methods: [GET, PUT, POST, PATCH, DELETE, OPTIONS] + defaults: + _controller: Drupal\quanthub_sdmx_proxy\Controller\Forwarder::forward_download + _title: 'SDMX API Proxy request forwarder' + requirements: + _permission: 'access content' From b4df577960b936200b9a2661d4656bf03ad997cd Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:53:25 +0300 Subject: [PATCH 19/43] Update Forwarder.php --- .../src/Controller/Forwarder.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php index 85deb8c..fa23c43 100644 --- a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php +++ b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php @@ -96,8 +96,23 @@ public function __construct( * The response object. */ public function forward(Request $request): Response { - $api_url = getenv('SDMX_API_URL'); + return forward_internal($request, getenv('SDMX_API_URL')); + } + + /** + * Forwards incoming requests to the connected API. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The incoming request. + * + * @return \Symfony\Component\HttpFoundation\Response + * The response object. + */ + public function forward_download(Request $request): Response { + return forward_internal($request, getenv('SDMX_DOWNLOAD_API_URL')); + } + private function forward_internal(Request $request, $api_url): Response { $headers = []; foreach ($request->headers->keys() as $key) { if (($key == 'content-type') || str_starts_with($key, 'accept') || str_starts_with($key, 'quanthub')) { From 8baff7bbd032e06cc7922be5f984d795d8df07c4 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:55:13 +0300 Subject: [PATCH 20/43] Update Forwarder.php --- modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php index fa23c43..a0ee20d 100644 --- a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php +++ b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php @@ -96,7 +96,7 @@ public function __construct( * The response object. */ public function forward(Request $request): Response { - return forward_internal($request, getenv('SDMX_API_URL')); + return forwardInternal($request, getenv('SDMX_API_URL')); } /** @@ -108,11 +108,11 @@ public function forward(Request $request): Response { * @return \Symfony\Component\HttpFoundation\Response * The response object. */ - public function forward_download(Request $request): Response { - return forward_internal($request, getenv('SDMX_DOWNLOAD_API_URL')); + public function forwardDownload(Request $request): Response { + return forwardInternal($request, getenv('SDMX_DOWNLOAD_API_URL')); } - private function forward_internal(Request $request, $api_url): Response { + private function forwardInternal(Request $request, $api_url): Response { $headers = []; foreach ($request->headers->keys() as $key) { if (($key == 'content-type') || str_starts_with($key, 'accept') || str_starts_with($key, 'quanthub')) { From 957def5ca16d942ba77747db193da68ccb0b6e02 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:55:31 +0300 Subject: [PATCH 21/43] Update quanthub_sdmx_proxy.routing.yml --- modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml b/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml index c176d8e..0a12c3f 100644 --- a/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml +++ b/modules/quanthub_sdmx_proxy/quanthub_sdmx_proxy.routing.yml @@ -19,7 +19,7 @@ sdmx_proxy.forwarder-download: path: '/sdmx-download' methods: [GET, PUT, POST, PATCH, DELETE, OPTIONS] defaults: - _controller: Drupal\quanthub_sdmx_proxy\Controller\Forwarder::forward_download + _controller: Drupal\quanthub_sdmx_proxy\Controller\Forwarder::forwardDownload _title: 'SDMX API Proxy request forwarder' requirements: _permission: 'access content' From 612f6b4bbf49ed5744f346c9c8c3fd9c1dd8b2af Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:58:13 +0300 Subject: [PATCH 22/43] Update Forwarder.php --- .../src/Controller/Forwarder.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php index a0ee20d..7853580 100644 --- a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php +++ b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php @@ -96,11 +96,11 @@ public function __construct( * The response object. */ public function forward(Request $request): Response { - return forwardInternal($request, getenv('SDMX_API_URL')); + return $this->forwardInternal($request, getenv('SDMX_API_URL')); } /** - * Forwards incoming requests to the connected API. + * Forwards incoming requests to the connected Download API. * * @param \Symfony\Component\HttpFoundation\Request $request * The incoming request. @@ -109,9 +109,20 @@ public function forward(Request $request): Response { * The response object. */ public function forwardDownload(Request $request): Response { - return forwardInternal($request, getenv('SDMX_DOWNLOAD_API_URL')); + return $this->forwardInternal($request, getenv('SDMX_DOWNLOAD_API_URL')); } + /** + * Forwards incoming requests to the connected API. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The incoming request. + * @param $api_url + * API URL. + * + * @return \Symfony\Component\HttpFoundation\Response + * The response object. + */ private function forwardInternal(Request $request, $api_url): Response { $headers = []; foreach ($request->headers->keys() as $key) { From be3d322273ecb7f7d37b1495f04f9d530c12c083 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Thu, 27 Jul 2023 20:01:19 +0300 Subject: [PATCH 23/43] Update Forwarder.php --- modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php index 7853580..c146d50 100644 --- a/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php +++ b/modules/quanthub_sdmx_proxy/src/Controller/Forwarder.php @@ -117,7 +117,7 @@ public function forwardDownload(Request $request): Response { * * @param \Symfony\Component\HttpFoundation\Request $request * The incoming request. - * @param $api_url + * @param string $api_url * API URL. * * @return \Symfony\Component\HttpFoundation\Response From 560b5025bffd4be7e24304b4f0115db7e43a03a5 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Tue, 1 Aug 2023 18:04:58 +0300 Subject: [PATCH 24/43] Update PathProcessor.php (#55) --- .../quanthub_sdmx_proxy/src/PathProcessor/PathProcessor.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/quanthub_sdmx_proxy/src/PathProcessor/PathProcessor.php b/modules/quanthub_sdmx_proxy/src/PathProcessor/PathProcessor.php index 5015552..02588e6 100644 --- a/modules/quanthub_sdmx_proxy/src/PathProcessor/PathProcessor.php +++ b/modules/quanthub_sdmx_proxy/src/PathProcessor/PathProcessor.php @@ -38,6 +38,12 @@ public function processInbound($path, Request $request) { $request->query->set('uri', $uri); return '/sdmx'; } + if (strpos($path, '/sdmx-download/') === 0) { + $requestUri = $this->requestStack->getCurrentRequest()->getRequestUri(); + $uri = preg_replace('|^\/sdmx-download|', '', $requestUri); + $request->query->set('uri', $uri); + return '/sdmx-download'; + } return $path; } From fc98fe5dc002907b39478ccb1a67f0a58518fc0f Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Fri, 4 Aug 2023 09:41:45 +0300 Subject: [PATCH 25/43] Force check powerbi token (#54) * Update powerbi-embed-formatter.html.twig * Update powerbi-embed-formatter.html.twig * Update powerbi-embed-formatter.html.twig * Update qh_core-power-bi-customizer.js --- modules/quanthub_core/js/qh_core-power-bi-customizer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/quanthub_core/js/qh_core-power-bi-customizer.js b/modules/quanthub_core/js/qh_core-power-bi-customizer.js index d324a88..9c7d389 100644 --- a/modules/quanthub_core/js/qh_core-power-bi-customizer.js +++ b/modules/quanthub_core/js/qh_core-power-bi-customizer.js @@ -52,6 +52,7 @@ function powerbi_embed_customizeReport($, context, width = 0, height = 0, title iframes[i].height = ih + 'px'; } + checkTokenAndUpdate($, context); setInterval(() => { checkTokenAndUpdate($, context); }, From f0fec1501a897231223e6c694966de4d7b8087d6 Mon Sep 17 00:00:00 2001 From: Artem Boyko Date: Wed, 16 Aug 2023 07:09:07 +0300 Subject: [PATCH 26/43] Updated jumbojett/openid-connect-php, added patch for updating phpseclib to minimum versions according to CWE-347 (#56) Co-authored-by: Artem Boiko --- composer.json | 42 ++++++++++++++++++++++++------------- composer.lock | 58 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index 04feec3..75520bf 100644 --- a/composer.json +++ b/composer.json @@ -1,17 +1,31 @@ { - "name": "epam/quanthub-portal", - "description": "Quanthub Portal Drupal Profile", - "type": "drupal-profile", - "require": { - "php": ">=8.0", - "jumbojett/openid-connect-php": "^0.9.6" - }, - "license": "GPL-3.0-or-later", - "authors": [ - { - "name": "Artem Boyko", - "email": "artemboyko43@gmail.com" + "name": "epam/quanthub-portal", + "description": "Quanthub Portal Drupal Profile", + "type": "drupal-profile", + "require": { + "php": ">=8.0", + "jumbojett/openid-connect-php": "^0.9.10", + "cweagans/composer-patches": "1.7.3" + }, + "license": "GPL-3.0-or-later", + "authors": [ + { + "name": "Artem Boyko", + "email": "artemboyko43@gmail.com" + } + ], + "minimum-stability": "dev", + "config": { + "allow-plugins": { + "cweagans/composer-patches": true + } + }, + "extra": { + "composer-exit-on-patch-failure": true, + "patches": { + "jumbojett/openid-connect-php": { + "Update minimum versions according to security check": "https://patch-diff.githubusercontent.com/raw/jumbojett/OpenID-Connect-PHP/pull/385.patch" + } + } } - ], - "minimum-stability": "dev" } diff --git a/composer.lock b/composer.lock index 3953aae..e598039 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,56 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5218c2a9ef9c09e487fc1847cc41250f", + "content-hash": "1c65f0d5da8668b2035a75c3bc872b4f", "packages": [ + { + "name": "cweagans/composer-patches", + "version": "1.7.3", + "source": { + "type": "git", + "url": "https://github.com/cweagans/composer-patches.git", + "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db", + "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3.0" + }, + "require-dev": { + "composer/composer": "~1.0 || ~2.0", + "phpunit/phpunit": "~4.6" + }, + "type": "composer-plugin", + "extra": { + "class": "cweagans\\Composer\\Patches" + }, + "autoload": { + "psr-4": { + "cweagans\\Composer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Cameron Eagans", + "email": "me@cweagans.net" + } + ], + "description": "Provides a way to patch Composer packages.", + "support": { + "issues": "https://github.com/cweagans/composer-patches/issues", + "source": "https://github.com/cweagans/composer-patches/tree/1.7.3" + }, + "time": "2022-12-20T22:53:13+00:00" + }, { "name": "jumbojett/openid-connect-php", "version": "v0.9.10", @@ -171,12 +219,12 @@ "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "b799abd1a0c387590c2f58ee3e12a640412b6031" + "reference": "c5e9d51e517da7c1b60a9198338ab1621351866f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/b799abd1a0c387590c2f58ee3e12a640412b6031", - "reference": "b799abd1a0c387590c2f58ee3e12a640412b6031", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c5e9d51e517da7c1b60a9198338ab1621351866f", + "reference": "c5e9d51e517da7c1b60a9198338ab1621351866f", "shasum": "" }, "require": { @@ -273,7 +321,7 @@ "type": "tidelift" } ], - "time": "2023-03-23T18:04:07+00:00" + "time": "2023-08-11T03:33:35+00:00" } ], "packages-dev": [], From 02d359dc0a50eb7a43b6fe538a766b683cd77120 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Wed, 16 Aug 2023 11:56:08 +0300 Subject: [PATCH 27/43] No special markup when no PowerBi embed token --- .../Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php b/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php index 622d8c3..7ac6404 100644 --- a/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php +++ b/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php @@ -155,7 +155,6 @@ public function viewElements(FieldItemListInterface $items, $langcode): array { } else { $elements[$delta] = [ - '#markup' => 'Issue generating PowerBi embed token. Please retry later', '#cache' => [ 'tags' => ['powerbi_embed:token'], 'max-age' => 0, From 198663b62e5a54e6e8095812fb12bbddcb256e4c Mon Sep 17 00:00:00 2001 From: Artem Boyko Date: Wed, 16 Aug 2023 13:05:30 +0300 Subject: [PATCH 28/43] Added wso ignore to anonymous user infor token subscriber (#58) Co-authored-by: Artem Boiko --- .../quanthub_core/src/AnonymousUserInfoTokenSubscriber.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php b/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php index fa01e7f..da0ce42 100644 --- a/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php +++ b/modules/quanthub_core/src/AnonymousUserInfoTokenSubscriber.php @@ -29,7 +29,9 @@ public function __construct(UserInfo $user_info) { * Check that token is existed. */ public function onRequest(RequestEvent $event) { - $this->userInfo->getToken(); + if (getenv('WSO_IGNORE') !== 'TRUE') { + $this->userInfo->getToken(); + } } /** From fe53c0fbecf0ab57d4840cc52730b9bfdcc4d9f3 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Mon, 21 Aug 2023 18:04:39 +0300 Subject: [PATCH 29/43] Fixed bug with creating power bi media in entity reference field --- modules/quanthub_core/src/Form/PowerBIMediaForm.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/quanthub_core/src/Form/PowerBIMediaForm.php b/modules/quanthub_core/src/Form/PowerBIMediaForm.php index b51f04d..cda8408 100644 --- a/modules/quanthub_core/src/Form/PowerBIMediaForm.php +++ b/modules/quanthub_core/src/Form/PowerBIMediaForm.php @@ -3,7 +3,9 @@ namespace Drupal\quanthub_core\Form; use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Url; use Drupal\media\MediaTypeInterface; use Drupal\media_library\Form\AddFormBase; @@ -31,6 +33,12 @@ protected function buildInputElement(array $form, FormStateInterface $form_state '#ajax' => [ 'callback' => '::updateFormCallback', 'wrapper' => 'media-library-wrapper', + 'url' => Url::fromRoute('media_library.ui'), + 'options' => [ + 'query' => $this->getMediaLibraryState($form_state)->all() + [ + FormBuilderInterface::AJAX_FORM_REQUEST => TRUE, + ], + ], ], ]; return $form; From 188eec7d28aaf5ca3c28d494bd2124134720862f Mon Sep 17 00:00:00 2001 From: Oleksandr Tiupa Date: Tue, 22 Aug 2023 18:31:40 +0300 Subject: [PATCH 30/43] changed gauge card link to /explorer with filters --- .../templates/content/node--gauge--details.html.twig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig index c82cb78..edba3f6 100644 --- a/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig +++ b/themes/quanthub_tailwindcss/templates/content/node--gauge--details.html.twig @@ -68,7 +68,9 @@ */ #} - +{% set quanthub_urn = node.field_dataset[0].entity.field_quanthub_urn.value %} + +
From 5c6a4b82c4e0961ab0ab56d40c7f197d41b5af78 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Tue, 22 Aug 2023 20:56:41 +0300 Subject: [PATCH 31/43] Fixed bug with default value for scale widget --- .../src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php index 8013606..b62e313 100644 --- a/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php +++ b/modules/quanthub_core/src/Plugin/Field/FieldWidget/QuantHubScaleNumberWidget.php @@ -28,6 +28,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $element = parent::formElement($items, $delta, $element, $form, $form_state); $element['value']['#type'] = 'select'; + $element['value']['#default_value'] = (integer) $element['value']['#default_value']; $element['value']['#options'] = [ 100 => $this->t('Hundreds'), 1000 => $this->t('Thousands'), From cc5af37879a8067a0ab6d5317cc7aaabaa215d67 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Wed, 23 Aug 2023 18:53:23 +0300 Subject: [PATCH 32/43] Removed curls, used Guzzle --- .../quanthub_core/quanthub_core.services.yml | 2 +- .../quanthub_core/src/PowerBIEmbedConfigs.php | 138 ++++++++++-------- 2 files changed, 76 insertions(+), 64 deletions(-) diff --git a/modules/quanthub_core/quanthub_core.services.yml b/modules/quanthub_core/quanthub_core.services.yml index 56836df..4a88b7e 100644 --- a/modules/quanthub_core/quanthub_core.services.yml +++ b/modules/quanthub_core/quanthub_core.services.yml @@ -47,7 +47,7 @@ services: powerbi_embed_configs: class: Drupal\quanthub_core\PowerBIEmbedConfigs - arguments: ['@config.factory', '@key.repository', '@logger.factory'] + arguments: ['@config.factory', '@key.repository', '@logger.factory', '@http_client'] # User Info Cache Context based on User Info Role for anonymous and User Id for others. cache_context.user_info_attributes: diff --git a/modules/quanthub_core/src/PowerBIEmbedConfigs.php b/modules/quanthub_core/src/PowerBIEmbedConfigs.php index f811098..971ebdc 100644 --- a/modules/quanthub_core/src/PowerBIEmbedConfigs.php +++ b/modules/quanthub_core/src/PowerBIEmbedConfigs.php @@ -6,6 +6,7 @@ use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\key\KeyRepositoryInterface; use Jumbojett\OpenIDConnectClient; +use GuzzleHttp\ClientInterface; /** * Return Power BI embed configs. @@ -33,6 +34,13 @@ class PowerBIEmbedConfigs { */ protected $loggerFactory; + /** + * The http client service. + * + * @var \GuzzleHttp\ClientInterface + */ + protected $httpClient; + /** * Constructor of PowerBIEmbedConfigs. * @@ -43,12 +51,16 @@ class PowerBIEmbedConfigs { * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory * The logger channel factory. */ - public function __construct(ConfigFactoryInterface $configFactory, - KeyRepositoryInterface $repository, - LoggerChannelFactoryInterface $loggerFactory) { + public function __construct( + ConfigFactoryInterface $configFactory, + KeyRepositoryInterface $repository, + LoggerChannelFactoryInterface $loggerFactory, + ClientInterface $httpClient + ) { $this->configFactory = $configFactory; $this->repository = $repository; $this->loggerFactory = $loggerFactory->get('powerbi_embed'); + $this->httpClient = $httpClient; } /** @@ -109,46 +121,49 @@ public function getPowerBiAccessToken() { * Get PowerBI Embed Token. */ public function getPowerBiEmbedToken($token, $reportId, $datasetIds) { - $bearerToken = "Authorization: Bearer " . $token; + $powerbiAPIURL = 'https://api.powerbi.com/v1.0/myorg/GenerateToken'; - $datasets = ''; + $datasets = []; foreach ($datasetIds as $datasetId) { - $datasets = $datasets . "{'id': '" . $datasetId . "', 'xmlaPermissions': 'ReadOnly'},"; + $datasets[] = [ + 'id' => $datasetId, + 'xmlaPermissions' => 'ReadOnly' + ]; + } - $curlPostToken = curl_init(); - $powerbiAPIURL = 'https://api.powerbi.com/v1.0/myorg/GenerateToken'; - $payload = "{ - 'datasets': [" . $datasets . "], - 'reports': [{'id': '" . $reportId . "'}], - 'targetWorkspaces': [{'id': '" . $this->getWorkspaceID() . "'}] - }"; - - $theCurlOpts = [ - CURLOPT_URL => $powerbiAPIURL, - CURLOPT_RETURNTRANSFER => TRUE, - CURLOPT_ENCODING => '', - CURLOPT_MAXREDIRS => 10, - CURLOPT_TIMEOUT => 30, - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => 'POST', - CURLOPT_POSTFIELDS => $payload, - CURLOPT_HTTPHEADER => [ - $bearerToken, - "Cache-Control: no-cache", - "Content-Type:application/json", - ], + $payload = [ + 'datasets' => $datasets, + 'reports' => [['id' => $reportId]], + 'targetWorkspaces' => [['id' => $this->getWorkspaceID()]] ]; - curl_setopt_array($curlPostToken, $theCurlOpts); - $tokenResponse = curl_exec($curlPostToken); - $tokenError = curl_error($curlPostToken); - curl_close($curlPostToken); - if ($tokenError) { - $this->loggerFactory->error("getPowerBIEmbedToken: " . $tokenError); + $payload_json = json_encode($payload); + + try { + $request = $this->httpClient->request( + 'POST', + $powerbiAPIURL, + [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + 'Cache-Control' => 'no-cache', + 'Content-Type' => 'application/json', + ], + 'connect_timeout' => 30, + 'allow_redirects' => [ + 'max' => 10 + ], + 'body' => $payload_json + ] + ); + } + catch (\Exception $e) { + $this->loggerFactory->error('getPowerBIEmbedToken: ' . $e->getMessage()); return NULL; } - $tokenResponse = json_decode($tokenResponse, TRUE); + + $tokenResponse = json_decode($request->getBody(), TRUE); if (isset($tokenResponse['error'])) { if (isset($tokenResponse['error']['message'])) { @@ -167,36 +182,33 @@ public function getPowerBiEmbedToken($token, $reportId, $datasetIds) { */ public function getPowerEmbedConfig($reportId, $extraDatasets) { $token = $this->getPowerBIAccessToken(); - $bearerToken = "Authorization: Bearer " . $token; - - $curlGetUrl = curl_init(); $powerbiAPIURL = 'https://api.powerbi.com/v1.0/myorg/groups/' . $this->getWorkspaceID() . '/reports/' . $reportId; - $theCurlOpts = [ - CURLOPT_URL => $powerbiAPIURL, - CURLOPT_RETURNTRANSFER => TRUE, - CURLOPT_ENCODING => '', - CURLOPT_MAXREDIRS => 10, - CURLOPT_TIMEOUT => 30, - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_CUSTOMREQUEST => 'GET', - CURLOPT_HTTPHEADER => [ - $bearerToken, - "Cache-Control: no-cache", - ], - ]; - curl_setopt_array($curlGetUrl, $theCurlOpts); - $embedResponse = curl_exec($curlGetUrl); - $embedError = curl_error($curlGetUrl); - curl_close($curlGetUrl); - if ($embedError) { - $this->loggerFactory->error("getPowerEmbedConfig: " . $embedError); + try { + $request = $this->httpClient->request( + 'GET', + $powerbiAPIURL, + [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + 'Cache-Control' => 'no-cache', + ], + 'connect_timeout' => 30, + 'allow_redirects' => [ + 'max' => 10 + ], + ] + ); + } + catch (\Exception $e) { + $this->loggerFactory->error('getPowerEmbedConfig: ' . $e->getMessage()); return NULL; } - $embedResponse = json_decode($embedResponse, TRUE); - if (isset($embedResponse["error"])) { - $this->loggerFactory->error("error: " . $embedResponse["error"]["message"]); + $embedResponse = json_decode($request->getBody(), TRUE); + + if (isset($embedResponse['error'])) { + $this->loggerFactory->error('error: ' . $embedResponse['error']['message']); return NULL; } @@ -205,15 +217,15 @@ public function getPowerEmbedConfig($reportId, $extraDatasets) { if (isset($extraDatasets) && !empty(trim($extraDatasets))) { $extraDatasets = preg_replace('/\s+/', ',', $extraDatasets); - $datasetIds = preg_split("/[,]+/", $extraDatasets); + $datasetIds = preg_split('/[,]+/', $extraDatasets); } $datasetIds[] = $datasetId; $embedToken = $this->getPowerBIEmbedToken($token, $reportId, $datasetIds); return [ - "embed_url" => $embedUrl, - "embed_token" => $embedToken, + 'embed_url' => $embedUrl, + 'embed_token' => $embedToken, ]; } From c7ae71e336e248aa646728a3c390b527dcd36418 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Wed, 23 Aug 2023 18:59:20 +0300 Subject: [PATCH 33/43] Fixed code standards --- modules/quanthub_core/src/PowerBIEmbedConfigs.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/quanthub_core/src/PowerBIEmbedConfigs.php b/modules/quanthub_core/src/PowerBIEmbedConfigs.php index 971ebdc..ef48fec 100644 --- a/modules/quanthub_core/src/PowerBIEmbedConfigs.php +++ b/modules/quanthub_core/src/PowerBIEmbedConfigs.php @@ -5,8 +5,8 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\key\KeyRepositoryInterface; -use Jumbojett\OpenIDConnectClient; use GuzzleHttp\ClientInterface; +use Jumbojett\OpenIDConnectClient; /** * Return Power BI embed configs. @@ -50,6 +50,8 @@ class PowerBIEmbedConfigs { * The key repository object. * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory * The logger channel factory. + * @param \GuzzleHttp\ClientInterface $httpClient + * The http client. */ public function __construct( ConfigFactoryInterface $configFactory, @@ -127,7 +129,7 @@ public function getPowerBiEmbedToken($token, $reportId, $datasetIds) { foreach ($datasetIds as $datasetId) { $datasets[] = [ 'id' => $datasetId, - 'xmlaPermissions' => 'ReadOnly' + 'xmlaPermissions' => 'ReadOnly', ]; } @@ -135,7 +137,7 @@ public function getPowerBiEmbedToken($token, $reportId, $datasetIds) { $payload = [ 'datasets' => $datasets, 'reports' => [['id' => $reportId]], - 'targetWorkspaces' => [['id' => $this->getWorkspaceID()]] + 'targetWorkspaces' => [['id' => $this->getWorkspaceID()]], ]; $payload_json = json_encode($payload); @@ -152,9 +154,9 @@ public function getPowerBiEmbedToken($token, $reportId, $datasetIds) { ], 'connect_timeout' => 30, 'allow_redirects' => [ - 'max' => 10 + 'max' => 10, ], - 'body' => $payload_json + 'body' => $payload_json, ] ); } @@ -195,7 +197,7 @@ public function getPowerEmbedConfig($reportId, $extraDatasets) { ], 'connect_timeout' => 30, 'allow_redirects' => [ - 'max' => 10 + 'max' => 10, ], ] ); From 8c7a138a290ee37057a631c0179227715a26f074 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:20:07 +0300 Subject: [PATCH 34/43] added FACETS_LOAD_HIERARCHIES env variable (#63) --- themes/quanthub_tailwindcss/quanthub_tailwindcss.theme | 2 ++ 1 file changed, 2 insertions(+) diff --git a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme index deabe8e..f38ac5d 100644 --- a/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme +++ b/themes/quanthub_tailwindcss/quanthub_tailwindcss.theme @@ -38,11 +38,13 @@ function quanthub_tailwindcss_preprocess_page(array &$variables) { $defaultCategorySchemeUrn = getenv('SDMX_DEFAULT_CATEGORY_SCHEME_URN'); $dataAttributeId = getenv('DATASET_EXPLORER_DATA_ATTRIBUTE_ID'); $unitsOfMeasureId = getenv('UNITS_OF_MEASURE_ATTRIBUTE_ID'); + $facetsLoadHierarchies = getenv('FACETS_LOAD_HIERARCHIES'); $variables['#attached']['drupalSettings']['workspaceId'] = $workspaceId; $variables['#attached']['drupalSettings']['defaultDataset'] = $defaultDataset; $variables['#attached']['drupalSettings']['defaultCategorySchemeUrn'] = $defaultCategorySchemeUrn; $variables['#attached']['drupalSettings']['dataAttributeId'] = $dataAttributeId; $variables['#attached']['drupalSettings']['unitsOfMeasureId'] = $unitsOfMeasureId; + $variables['#attached']['drupalSettings']['facetsLoadHierarchies'] = $facetsLoadHierarchies; } /** From 1a7207f923cf95b3c7a3dd8542d33e6d401552cc Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Mon, 28 Aug 2023 19:07:23 +0300 Subject: [PATCH 35/43] Added validation for power bi api route --- .../src/Controller/PowerBIEmbedController.php | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php index 358a106..681c72d 100644 --- a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php +++ b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php @@ -2,8 +2,11 @@ namespace Drupal\quanthub_core\Controller; +use Drupal\Component\Uuid\Uuid; use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\Entity\EntityTypeManager; use Drupal\quanthub_core\PowerBIEmbedConfigs; +use GuzzleHttp\Psr7\Response; use Laminas\Diactoros\Response\JsonResponse; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -20,6 +23,13 @@ class PowerBIEmbedController extends ControllerBase { */ protected $powerBIEmbedConfigs; + /** + * The EntityTypeManager service. + * + * @var \Drupal\Core\Entity\EntityTypeManager + */ + protected $entityTypeManager; + /** * Create a PowerBIEmbedController instance. * @@ -28,7 +38,8 @@ class PowerBIEmbedController extends ControllerBase { */ public static function create(ContainerInterface $container) { return new static( - $container->get('powerbi_embed_configs') + $container->get('powerbi_embed_configs'), + $container->get('entity_type.manager') ); } @@ -37,17 +48,37 @@ public static function create(ContainerInterface $container) { * * @param \Drupal\quanthub_core\PowerBIEmbedConfigs $powerBIEmbedConfigs * The PowerBIEmbedConfigs object. + * @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager + * The EntityTypeManager service. */ - public function __construct(PowerBIEmbedConfigs $powerBIEmbedConfigs) { + public function __construct(PowerBIEmbedConfigs $powerBIEmbedConfigs, EntityTypeManager $entityTypeManager) { $this->powerBIEmbedConfigs = $powerBIEmbedConfigs; + $this->entityTypeManager = $entityTypeManager; } /** * Return Power BI embed configs in the json format. */ - public function postData($reportId, Request $request): JsonResponse { - $content = json_decode($request->getContent(), TRUE); - return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig($reportId, $content["extraDatasets"])); + public function postData($reportId, Request $request): JsonResponse | Response { + if (Uuid::isValid($reportId)) { + $media_storage = $this->entityTypeManager->getStorage('media'); + $media_ids = $media_storage->getQuery() + ->condition('bundle', 'power_bi') + ->condition('field_media_power_bi.report_id', $reportId) + ->execute(); + + try { + $content = json_decode($request->getContent(), TRUE, 3, JSON_THROW_ON_ERROR); + if (!empty($content['extraDatasets']) && !empty($media_ids)) { + return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig($reportId, $content['extraDatasets'])); + } + } + catch (\Exception) { + return new Response(400); + } + } + + return new Response(400); } } From 4f1943e56835c3d1b174bcb8a8399940a784f0c1 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Mon, 28 Aug 2023 19:16:42 +0300 Subject: [PATCH 36/43] Corrected logic of conditions --- .../src/Controller/PowerBIEmbedController.php | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php index 681c72d..e2ee104 100644 --- a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php +++ b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php @@ -5,6 +5,7 @@ use Drupal\Component\Uuid\Uuid; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\EntityTypeManager; +use Drupal\facets\Exception\Exception; use Drupal\quanthub_core\PowerBIEmbedConfigs; use GuzzleHttp\Psr7\Response; use Laminas\Diactoros\Response\JsonResponse; @@ -60,25 +61,29 @@ public function __construct(PowerBIEmbedConfigs $powerBIEmbedConfigs, EntityType * Return Power BI embed configs in the json format. */ public function postData($reportId, Request $request): JsonResponse | Response { - if (Uuid::isValid($reportId)) { - $media_storage = $this->entityTypeManager->getStorage('media'); - $media_ids = $media_storage->getQuery() - ->condition('bundle', 'power_bi') - ->condition('field_media_power_bi.report_id', $reportId) - ->execute(); + if (!Uuid::isValid($reportId)) { + return new Response(400); + } + + $media_storage = $this->entityTypeManager->getStorage('media'); + $media_ids = $media_storage->getQuery() + ->condition('bundle', 'power_bi') + ->condition('field_media_power_bi.report_id', $reportId) + ->execute(); - try { - $content = json_decode($request->getContent(), TRUE, 3, JSON_THROW_ON_ERROR); - if (!empty($content['extraDatasets']) && !empty($media_ids)) { - return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig($reportId, $content['extraDatasets'])); - } + try { + $content = json_decode($request->getContent(), TRUE, 3, JSON_THROW_ON_ERROR); + if (!empty($content['extraDatasets']) && !empty($media_ids)) { + return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig($reportId, $content['extraDatasets'])); } - catch (\Exception) { - return new Response(400); + else { + throw new Exception('Not enough data'); } } + catch (\Exception) { + return new Response(400); + } - return new Response(400); } } From 45ce78aaac86328c90f163b9b6fce785fd861197 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Tue, 29 Aug 2023 07:15:41 +0300 Subject: [PATCH 37/43] Make extraDatasets optional --- .../src/Controller/PowerBIEmbedController.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php index e2ee104..be10c34 100644 --- a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php +++ b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php @@ -70,20 +70,17 @@ public function postData($reportId, Request $request): JsonResponse | Response { ->condition('bundle', 'power_bi') ->condition('field_media_power_bi.report_id', $reportId) ->execute(); + if (empty($media_ids)) { + return new Response(400); + } try { $content = json_decode($request->getContent(), TRUE, 3, JSON_THROW_ON_ERROR); - if (!empty($content['extraDatasets']) && !empty($media_ids)) { - return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig($reportId, $content['extraDatasets'])); - } - else { - throw new Exception('Not enough data'); - } + return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig($reportId, $content['extraDatasets'])); } catch (\Exception) { return new Response(400); } - } } From b8f971b117c30c95245569596fea52b8af54f146 Mon Sep 17 00:00:00 2001 From: Illya Havsiyevych <44289086+illya-havsiyevych@users.noreply.github.com> Date: Tue, 29 Aug 2023 07:18:38 +0300 Subject: [PATCH 38/43] Remove unused import --- modules/quanthub_core/src/Controller/PowerBIEmbedController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php index be10c34..d01e4f6 100644 --- a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php +++ b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php @@ -5,7 +5,6 @@ use Drupal\Component\Uuid\Uuid; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\EntityTypeManager; -use Drupal\facets\Exception\Exception; use Drupal\quanthub_core\PowerBIEmbedConfigs; use GuzzleHttp\Psr7\Response; use Laminas\Diactoros\Response\JsonResponse; From 38e6317bc53b5f96c674e969f5792d3379880f1c Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Tue, 29 Aug 2023 12:00:34 +0300 Subject: [PATCH 39/43] Refactored code --- .../quanthub_core/src/Controller/PowerBIEmbedController.php | 5 ++++- modules/quanthub_core/src/PowerBIEmbedConfigs.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php index d01e4f6..c31b1d9 100644 --- a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php +++ b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php @@ -75,7 +75,10 @@ public function postData($reportId, Request $request): JsonResponse | Response { try { $content = json_decode($request->getContent(), TRUE, 3, JSON_THROW_ON_ERROR); - return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig($reportId, $content['extraDatasets'])); + return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig( + $reportId, + !empty($content['extraDatasets']) ?: '' + )); } catch (\Exception) { return new Response(400); diff --git a/modules/quanthub_core/src/PowerBIEmbedConfigs.php b/modules/quanthub_core/src/PowerBIEmbedConfigs.php index ef48fec..9e36194 100644 --- a/modules/quanthub_core/src/PowerBIEmbedConfigs.php +++ b/modules/quanthub_core/src/PowerBIEmbedConfigs.php @@ -182,7 +182,7 @@ public function getPowerBiEmbedToken($token, $reportId, $datasetIds) { /** * Get PowerBI Embed Config Embed url and Embed token. */ - public function getPowerEmbedConfig($reportId, $extraDatasets) { + public function getPowerEmbedConfig($reportId, $extraDatasets = '') { $token = $this->getPowerBIAccessToken(); $powerbiAPIURL = 'https://api.powerbi.com/v1.0/myorg/groups/' . $this->getWorkspaceID() . '/reports/' . $reportId; From 727de7b0b845c6c1a98b3bf15e4cc7912bd865ad Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Tue, 29 Aug 2023 18:01:45 +0300 Subject: [PATCH 40/43] Refactored power bi code, removed no needed max-age, as we invalidate tags for power bi each 15 mins and check token alive --- .../QuantHubPowerBIEmbedFormatter.php | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php b/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php index 7ac6404..6c93941 100644 --- a/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php +++ b/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php @@ -102,27 +102,20 @@ public function viewElements(FieldItemListInterface $items, $langcode): array { $workspace_id = $this->powerBIEmbedConfigs->getWorkspaceID(); foreach ($items as $delta => $item) { - if (isset($item->report_id) && !empty($item->report_id)) { + if (!empty($item->report_id)) { $embed_config = $this->powerBIEmbedConfigs->getPowerEmbedConfig($item->report_id, $item->report_extra_datasets); - $embed_token = $embed_config["embed_token"]; - $embed_url = $embed_config["embed_url"]; + $embed_token = $embed_config['embed_token']; + $embed_url = $embed_config['embed_url']; if (isset($embed_token)) { - // @todo Implement DI. - $expiration = DateTimePlus::createFromFormat('Y-m-d\TH:i:s\Z', $embed_token["expiration"]); - $max_age = $expiration->getTimestamp() - (new DateTimePlus())->getTimestamp() - 15; - if ($max_age < 0) { - $max_age = 0; - } - $embed_type = 'report'; $embed_id = $item->report_id; - if (isset($item->report_page) && !empty($item->report_page)) { + if (!empty($item->report_page)) { $embed_id = $embed_id . '_' . preg_replace('/\s+/', '_', $item->report_page); } - if (isset($item->report_visual) && !empty($item->report_visual)) { + if (!empty($item->report_visual)) { $embed_id = $embed_id . '_' . preg_replace('/\s+/', '_', $item->report_visual); $embed_type = 'visual'; } @@ -142,14 +135,13 @@ public function viewElements(FieldItemListInterface $items, $langcode): array { '#report_page' => $item->report_page, '#report_visual' => $item->report_visual, '#workspace_id' => $workspace_id, - '#token_expiration' => $embed_token["expiration"], + '#token_expiration' => $embed_token['expiration'], '#extra_datasets' => $item->report_extra_datasets, - '#token' => $embed_token["token"], + '#token' => $embed_token['token'], '#embed_url' => $embed_url, '#theme' => 'powerbi_embed_formatter', '#cache' => [ 'tags' => ['powerbi_embed:token'], - 'max-age' => $max_age, ], ]; } @@ -157,7 +149,6 @@ public function viewElements(FieldItemListInterface $items, $langcode): array { $elements[$delta] = [ '#cache' => [ 'tags' => ['powerbi_embed:token'], - 'max-age' => 0, ], ]; } From b2e54c3a81eea68231be954d21450a7d0d4f1458 Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Tue, 29 Aug 2023 18:10:31 +0300 Subject: [PATCH 41/43] Removed unused use --- .../Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php b/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php index 6c93941..ce69b06 100644 --- a/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php +++ b/modules/quanthub_core/src/Plugin/Field/FieldFormatter/QuantHubPowerBIEmbedFormatter.php @@ -2,7 +2,6 @@ namespace Drupal\quanthub_core\Plugin\Field\FieldFormatter; -use Drupal\Component\Datetime\DateTimePlus; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; From 90f91c3bb874e198cd5217f21d93eb031f0a2d6b Mon Sep 17 00:00:00 2001 From: Artem Boiko Date: Wed, 30 Aug 2023 14:47:53 +0300 Subject: [PATCH 42/43] Fixed bug with embed token refactored code --- modules/quanthub_core/src/Controller/PowerBIEmbedController.php | 2 +- modules/quanthub_core/src/PowerBIEmbedConfigs.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php index c31b1d9..93cfa47 100644 --- a/modules/quanthub_core/src/Controller/PowerBIEmbedController.php +++ b/modules/quanthub_core/src/Controller/PowerBIEmbedController.php @@ -77,7 +77,7 @@ public function postData($reportId, Request $request): JsonResponse | Response { $content = json_decode($request->getContent(), TRUE, 3, JSON_THROW_ON_ERROR); return new JsonResponse($this->powerBIEmbedConfigs->getPowerEmbedConfig( $reportId, - !empty($content['extraDatasets']) ?: '' + !empty($content['extraDatasets']) ? $content['extraDatasets'] : '' )); } catch (\Exception) { diff --git a/modules/quanthub_core/src/PowerBIEmbedConfigs.php b/modules/quanthub_core/src/PowerBIEmbedConfigs.php index 9e36194..0ab7e56 100644 --- a/modules/quanthub_core/src/PowerBIEmbedConfigs.php +++ b/modules/quanthub_core/src/PowerBIEmbedConfigs.php @@ -217,7 +217,7 @@ public function getPowerEmbedConfig($reportId, $extraDatasets = '') { $embedUrl = $embedResponse['embedUrl']; $datasetId = $embedResponse['datasetId']; - if (isset($extraDatasets) && !empty(trim($extraDatasets))) { + if (!empty(trim($extraDatasets))) { $extraDatasets = preg_replace('/\s+/', ',', $extraDatasets); $datasetIds = preg_split('/[,]+/', $extraDatasets); } From 93eec9200b06cba717fc6a1d3259194a3c26815c Mon Sep 17 00:00:00 2001 From: Oleksandr Tiupa Date: Fri, 1 Sep 2023 14:58:53 +0300 Subject: [PATCH 43/43] changed name of Dataset explorer to Data Bank --- .../quanthub_datasetexplorer/src/Controller/DatasetExplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quanthub_datasetexplorer/src/Controller/DatasetExplorer.php b/modules/quanthub_datasetexplorer/src/Controller/DatasetExplorer.php index d38c8e2..6ae68a3 100644 --- a/modules/quanthub_datasetexplorer/src/Controller/DatasetExplorer.php +++ b/modules/quanthub_datasetexplorer/src/Controller/DatasetExplorer.php @@ -161,7 +161,7 @@ public function explorer(Request $request) { * Returns translatable page title. */ public function getTitle(): string { - return $this->t('Dataset Explorer'); + return $this->t('Data Bank'); } }