acquia_perz-4.0.0-rc1/src/PerzHelper.php
src/PerzHelper.php
<?php
namespace Drupal\acquia_perz;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Theme\ActiveTheme;
/**
* Perz helper class.
*/
class PerzHelper {
/**
* Returns a unique hash for the current site.
*
* @return string
* A unique site hash, containing only alphanumeric characters.
*/
public static function getSiteId(): string {
$config = \Drupal::configFactory()->get('acquia_perz.settings');
$site_id = $config->get('api.site_id') ?? '';
if ($site_id == '' && \Drupal::moduleHandler()->moduleExists('acquia_lift')) {
$site_id = \Drupal::configFactory()->get('acquia_lift.settings')->get('credential.site_id') ?? '';
}
return $site_id;
}
/**
* Returns a environment variable.
*
* @return string
* An acquia site environment.
*/
public static function getSiteEnvironment(): string {
// During Beta, only production environment is supported.
return 'prod';
}
/**
* Get a site domain.
*
* @return string
* Returns a site domain.
*/
public static function getSiteDomain(): string {
return \Drupal::requestStack()->getCurrentRequest()->getHost();
}
/**
* Get a site domain with host.
*
* @return string
* Returns a site domain with host.
*/
public static function getSiteDomainWithHost(): string {
return \Drupal::requestStack()->getCurrentRequest()->getSchemeAndHttpHost();
}
/**
* Get account id.
*
* @return string|null
* Returns account id.
*/
public static function getAccountId(): ?string {
$subscription = \Drupal::service('acquia_connector.subscription');
$subscription_data = $subscription->getSubscription();
if (isset($subscription_data['acquia_perz'])) {
return $subscription_data['acquia_perz']['account_id'];
}
return NULL;
}
/**
* Collect imagefields for a particular entity bundle.
*
* @param string $entity_type_id
* The entity type identifier.
* @param string $bundle
* The bundle name.
*
* @return array
* The array of image fields for a given entity bundle.
*/
public static function collectImageFields(string $entity_type_id, string $bundle): array {
$image_fields = [];
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type_id, $bundle);
foreach ($field_definitions as $field_key => $field_definition) {
if ($field_definition->getType() === 'image') {
$image_fields[$field_key] = $field_definition->getLabel();
}
}
return $image_fields;
}
/**
* Remove/update data from settings configuration.
*
* @param string $entity_type_id
* The entity type id.
* @param string $bundle
* The bundle of entity type.
* @param string $view_mode
* The view_mode of bundle.
* @param array $data
* User input data.
* @param array $config_view_mode
* Config_view_mode of previous store data.
*/
public static function removeViewModeFromConfig(string $entity_type_id, string $bundle, string $view_mode, array $data, array &$config_view_mode): void {
$entity_view_perz_config = array_filter($data['view_mode']);
if ((!empty($config_view_mode) && isset($config_view_mode[$entity_type_id][$bundle])
&& array_key_exists($view_mode, $config_view_mode[$entity_type_id][$bundle]))
&& empty($entity_view_perz_config)) {
if (count($config_view_mode[$entity_type_id][$bundle]) > 1) {
unset($config_view_mode[$entity_type_id][$bundle][$view_mode]);
}
elseif (count($config_view_mode[$entity_type_id]) > 1) {
unset($config_view_mode[$entity_type_id][$bundle]);
}
else {
unset($config_view_mode[$entity_type_id]);
}
}
else {
if (!empty($entity_view_perz_config)) {
$role['render_role'] = $data['render_role'];
$preview_image = isset($data['acquia_perz_preview_image']) ? ['preview_image' => $data['acquia_perz_preview_image']] : [];
$personalization_label = isset($data['personalization_label']) ? ['personalization_label' => $data['personalization_label']] : [];
$only_export_specific_entities = isset($data['only_export_specific_entities']) ? ['only_export_specific_entities' => $data['only_export_specific_entities']] : [];
$config_view_mode[$entity_type_id][$bundle][$view_mode] = array_merge($role, $preview_image, $personalization_label, $only_export_specific_entities);
}
}
}
/**
* Get view mode minimal HTML.
*
* @param \Drupal\Core\Entity\EntityInterface $object
* The content entity object.
* @param string $view_mode
* The view mode identifier.
* @param string $lang_code
* The Language code.
*
* @return array|null
* The view mode minimal HTML.
*/
public static function getViewModeMinimalHtml(EntityInterface $object, string $view_mode, string $lang_code): array|null {
$entity_type_id = $object->getEntityTypeId();
if ($entity_type_id === 'block_content') {
$build = self::getBlockMinimalBuildArray($object, $view_mode, $lang_code);
}
else {
$build = self::getViewMode($object, $view_mode, $lang_code);
}
return $build;
}
/**
* Run decision webhook.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public static function runDecisionWebhook(EntityInterface $entity = NULL): void {
$config = \Drupal::configFactory()->get('acquia_perz.settings');
$decision_endpoint = $config->get('api.endpoint');
if (empty($decision_endpoint)
|| \Drupal::moduleHandler()->moduleExists('acquia_perz_push')
|| !\Drupal::service('entity_helper')->isValidEntity($entity)) {
return;
}
$data = [
'account_id' => self::getAccountId(),
'origin' => self::getSiteId(),
'environment' => self::getSiteEnvironment(),
'domain' => self::getSiteDomain(),
'entity_type' => $entity->getEntityTypeId(),
'entity_uuid' => $entity->uuid(),
'site_hash' => self::getSiteHash(),
];
\Drupal::service('client_factory')->pushEntity($data);
}
/**
* Get Active Theme.
*
* @return \Drupal\Core\Theme\ActiveTheme
* The active theme object.
*/
public static function getActiveTheme(): ActiveTheme {
return \Drupal::service('theme.manager')->getActiveTheme();
}
/**
* Get Default Theme.
*
* @return \Drupal\Core\Theme\ActiveTheme
* The active theme object.
*/
public static function getActiveDefaultTheme(): ActiveTheme {
$activeDefaultThemeName = \Drupal::configFactory()->get('system.theme')->get('default');
return \Drupal::service('theme.initialization')->getActiveThemeByName($activeDefaultThemeName);
}
/**
* Set Active Theme.
*
* @param \Drupal\Core\Theme\ActiveTheme $theme
* The active theme object.
*/
public static function setActiveTheme(ActiveTheme $theme): void {
\Drupal::service('theme.initialization')->loadActiveTheme($theme);
\Drupal::service('theme.manager')->setActiveTheme($theme);
}
/**
* Safely switches to another account.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The account to switch to.
*/
public static function switchAccountTo(AccountInterface $account): void {
\Drupal::service('account_switcher')->switchTo($account);
}
/**
* Reverts to a previous account after switching.
*/
public static function switchAccountBack(): void {
\Drupal::service('account_switcher')->switchBack();
}
/**
* Creates a unique hash for the current site.
*
* @return string
* A unique hash, containing only alphanumeric characters.
*/
public static function createSiteHash(): string {
$base_url = \Drupal::requestStack()->getCurrentRequest()->getHost();
$hash = substr(base_convert(hash('sha256', uniqid($base_url, TRUE)), 16, 36), 0, 6);
\Drupal::state()->set('acquia_perz.site_hash', $hash);
return $hash;
}
/**
* Returns a unique hash for the current site.
*
* @return string
* A unique hash, containing only alphanumeric characters.
*/
public static function getSiteHash(): string {
if (!($hash = \Drupal::state()->get('acquia_perz.site_hash', FALSE))) {
$hash = self::createSiteHash();
}
return $hash;
}
/**
* Renders block using BlockViewBuilder.
*
* @param \Drupal\Core\Entity\EntityInterface $object
* The Content Entity Object.
* @param string $view_mode
* The request view mode identifier.
* @param string $lang_code
* The Language code.
*
* @return array
* Render array for the block.
*/
public static function getBlockMinimalBuildArray(EntityInterface $object, string $view_mode, string $lang_code): array {
$block = \Drupal::service('plugin.manager.block')->createInstance('block_content:' . $object->uuid());
$build = [
'#theme' => 'block',
'#attributes' => [],
'#contextual_links' => [],
'#weight' => 0,
'#configuration' => $block->getConfiguration(),
'#plugin_id' => $block->getPluginId(),
'#base_plugin_id' => $block->getBaseId(),
'#derivative_plugin_id' => $block->getDerivativeId(),
];
// Block entity itself doesn't have configuration.
$block->setConfigurationValue('view_mode', $view_mode);
$build['#configuration']['view_mode'] = $view_mode;
// See \Drupal\block\BlockViewBuilder::preRender() for reference.
$content = self::getViewMode($object, $view_mode, $lang_code);
if ($content !== NULL && !Element::isEmpty($content)) {
foreach (['#attributes', '#contextual_links'] as $property) {
if (isset($content[$property])) {
$build[$property] += $content[$property];
unset($content[$property]);
}
}
}
$build['content'] = $content;
return $build;
}
/**
* Returns the applicable render array.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The renderable entity.
* @param string $view_mode
* The view mode to render in.
* @param string $lang_code
* The Language code.
*
* @return array|null
* The render array.
*/
public static function getViewMode(EntityInterface $entity, string $view_mode, string $lang_code): array|null {
return \Drupal::entityTypeManager()
->getViewBuilder($entity->getEntityTypeId())
->view($entity, $view_mode, $lang_code);
}
/**
* Override Acquia Lift settings.
*/
public static function shouldOverrideLiftSettings() {
$override_lift = \Drupal::configFactory()->get('acquia_perz.settings')->get('override_lift_meta_tags');
if (\Drupal::moduleHandler()->moduleExists('acquia_lift') && !$override_lift) {
return FALSE;
}
return TRUE;
}
/**
* Migrate Site ID.
*/
public static function migrateSiteId(): void {
if (\Drupal::moduleHandler()->moduleExists('acquia_lift')) {
$acquia_lift_settings = \Drupal::configFactory()->get('acquia_lift.settings');
$acquia_perz_settings = \Drupal::configFactory()->getEditable('acquia_perz.settings');
if (!empty($acquia_lift_settings->get('credential.site_id'))) {
$acquia_perz_settings->set('api.site_id', $acquia_lift_settings->get('credential.site_id'));
}
$acquia_perz_settings->save();
}
}
/**
* Get Personalization Regions.
*
* @return array
* Returns array of Personalization regions.
*/
public static function getRegions(): array {
return [
'us' => 'The Americas',
'eu' => 'Europe',
'ap' => 'Asia-Pacific',
'demo' => 'Demo',
];
}
/**
* Get Regions Endpoint.
*
* @param string $region
* Region code.
*
* @return string
* Returns Endpoint url for the region.
*/
public static function getRegionEndpoint(string $region = 'us'): string {
switch ($region) {
case 'eu':
return 'https://eu.perz-api.cloudservices.acquia.io';
case 'ap':
return 'https://ap.perz-api.cloudservices.acquia.io';
case 'demo':
return 'https://demo.perz-api.cloudservices.acquia.io';
default:
return 'https://us.perz-api.cloudservices.acquia.io';
}
}
/**
* Returns the value of only_export_certain_entities field.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The current entity.
* @param string $only_export_certain_entities_field
* The field which indicates if the entity should be exported or not.
*
* @return string
* The value of only_export_certain_entities field.
*/
public static function getExportFieldValue(EntityInterface $entity, string $only_export_certain_entities_field): string {
$only_export_certain_entities_value = '';
if ($only_export_certain_entities_field !== '') {
if ($entity->$only_export_certain_entities_field) {
$only_export_certain_entities_value = $entity->$only_export_certain_entities_field->value;
}
}
return $only_export_certain_entities_value;
}
/**
* Get configuration error messages.
*
* @return array
* Returns array of config error messages.
*/
public static function getConfigErrorMessages(): array {
$site_id = PerzHelper::getSiteId();
$configErrorMessages = [];
// Check if acquia_perz_push is disabled.
if (!\Drupal::moduleHandler()->moduleExists('acquia_perz_push')) {
$configErrorMessages[] = t('The Acquia Personalization Push module is uninstalled. Please install this module.');
}
// Check if API Credentials are valid.
$api_credentials_error_message = self::getErrorMessageForInvalidApiCredentials();
if ($api_credentials_error_message) {
$configErrorMessages[] = $api_credentials_error_message;
}
// Check for missing site ID.
if (!$site_id) {
$configErrorMessages[] = t('Site ID is missing.');
}
return $configErrorMessages;
}
/**
* Get error message for invalid API credentials.
*
* @return string
* Returns a error message for invalid API credentials
*/
private static function getErrorMessageForInvalidApiCredentials(): string {
$data = [
'account_id' => PerzHelper::getAccountId(),
'origin' => PerzHelper::getSiteId(),
'environment' => PerzHelper::getSiteEnvironment(),
];
$errorMessage = '';
try {
$response = \Drupal::service('acquia_perz.client_factory')->getEntities($data);
// Fetch status code from here, add error message if code !=200.
}
catch (\Exception $e) {
$errorMessage = t('Unable to connect to the Acquia Personalization service. Please check your Acquia Personalization credentials in the Acquia Connector settings form.');
}
return $errorMessage;
}
/**
* Attach libraries required to render the element.
*
* @param array $page
* Array of all attachments required for page.
*/
public static function attachLibrariesForPerz(array &$page) {
$elementLibraries = \Drupal::state()->get('acquia_perz.libraries', []);
foreach ($elementLibraries as $libraries) {
foreach ($libraries as $library) {
$page['#attached']['library'][] = $library;
}
}
$page['#attached']['library'][] = 'acquia_perz/acquia_perz';
}
/**
* Saves the required Libraries to Drupal State.
*
* @param string $entity_uuid
* UUID of the entity.
* @param array $libraries
* Array of libraries required by elements.
*/
public static function saveLibrariesForPerz(string $entity_uuid, array $libraries) {
$elementLibraries = \Drupal::state()->get('acquia_perz.libraries');
$elementLibraries[$entity_uuid] = $libraries;
\Drupal::state()->set('acquia_perz.libraries', $elementLibraries);
}
/**
* Delete the required Libraries from Drupal State.
*
* @param string $entity_uuid
* UUID of the entity.
*/
public static function deleteLibrariesForPerz(string $entity_uuid) {
$elementLibraries = \Drupal::state()->get('acquia_perz.libraries');
if (!empty($elementLibraries) && array_key_exists($entity_uuid, $elementLibraries)) {
unset($elementLibraries[$entity_uuid]);
\Drupal::state()->set('acquia_perz.libraries', $elementLibraries);
}
}
/**
* Clears libraries from state.
*/
public static function clearLibrariesFromState() {
\Drupal::state()->set('acquia_perz.libraries', NULL);
}
}
