Skip to content
Snippets Groups Projects
Commit b4af49fd authored by Timothy Zura's avatar Timothy Zura Committed by Ari Hylas
Browse files

Resolve #3457025 "Allow promoted result"

parent 6add8439
No related branches found
No related tags found
1 merge request!2Resolve #3457025 "Allow promoted result"
Pipeline #213107 passed
name: ddev-drupal-contrib
repository: ddev/ddev-drupal-contrib
version: 1.0.0-rc17
install_date: "2024-06-05T23:01:06-06:00"
version: 1.0.0-rc18
install_date: "2024-06-25T15:28:24-06:00"
project_files:
- commands
- commands/web/eslint
- commands/web/expand-composer-json
- commands/web/nightwatch
- commands/web/phpcbf
- commands/web/phpcs
- commands/web/phpunit
- commands/web/poser
- commands/web/stylelint
- commands/web/symlink-project
- config.contrib.yaml
global_files: []
removal_actions: []
......@@ -18,5 +18,5 @@ if [ -f "phpunit.xml" ]; then
phpunit "$@"
else
# Bootstrap Drupal tests and run all custom module tests.
phpunit --printer="\Drupal\Tests\Listeners\HtmlOutputPrinter" --bootstrap $PWD/$DDEV_DOCROOT/core/tests/bootstrap.php --testdox $DDEV_DOCROOT/modules/custom "$@"
phpunit --printer="\Drupal\Tests\Listeners\HtmlOutputPrinter" --bootstrap $PWD/$DDEV_DOCROOT/core/tests/bootstrap.php $DDEV_DOCROOT/modules/custom "$@"
fi
name: vais-promos
type: php
type: drupal10
docroot: web
php_version: "8.2"
webserver_type: nginx-fpm
......@@ -273,3 +273,7 @@ web_environment: []
# information on the commands that can be extended and the tasks you can define
# for them. Example:
#hooks:
# post-import-db:
# - exec: drush sql:sanitize
# - exec: drush updatedb
# - exec: drush cache:rebuild
ol.search-results .promotion{
ol.search-results .promotion {
width: 55%;
padding: 1em;
border-color: #fff;
......
......@@ -261,16 +261,39 @@ class VaisPromo extends ContentEntityBase implements VaisPromoInterface {
->setDescription(t('The UUID of the Promo entity.'))
->setReadOnly(TRUE);
// Specify the type of promoted result (content reference or external link).
$fields['promo_type'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Promoted Result Type'))
->setDescription(t('The type of Promoted Result.'))
->setRequired(TRUE)
->setSettings([
'allowed_values' => [
'internal' => t('Internal'),
'external' => t('External'),
],
])
->setDisplayOptions('view', [
'label' => 'visible',
'type' => 'list_default',
'weight' => -5,
])
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => -5,
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);
// Reference to the node that will appear if promotion is triggered.
$fields['promo_content'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Promotion Reference'))
->setDescription(t('Content to present if promotion is triggered.'))
->setLabel(t('Content Reference'))
->setDescription(t('Reference the promoted content.'))
->setSetting('target_type', 'node')
->setSetting('handler', 'default:node')
->setSetting('handler_settings', [
'auto_create' => FALSE,
])
->setRequired(TRUE)
->setRequired(FALSE)
->setTranslatable(FALSE)
->setDisplayOptions('view', [
'label' => 'visible',
......@@ -288,14 +311,35 @@ class VaisPromo extends ContentEntityBase implements VaisPromoInterface {
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);
// External link to which the promoted result is associated.
$fields['promo_link'] = BaseFieldDefinition::create('string')
->setLabel(t('External Link'))
->setDescription(t('Provide the promoted result external link.'))
->setRequired(FALSE)
->setSettings([
'default_value' => '',
'max_length' => 255,
'text_processing' => 0,
])
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'string',
'weight' => -4,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -4,
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);
// When displaying the promo content on the SERP, override the node title.
$fields['promo_title_override'] = BaseFieldDefinition::create('string')
->setLabel(t('Promotion Title Override'))
->setLabel(t('Promotion Title'))
->setDescription(t(
'If unspecified, title of Referenced Promotion Content will display.'
'The displayed title of the promoted result.'
))
->setDefaultValue('')
->setRequired(FALSE)
->setRequired(TRUE)
->setSettings([
'default_value' => '',
'max_length' => 255,
......
......@@ -3,6 +3,7 @@
namespace Drupal\vais_promos\Form;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityRepositoryInterface;
......@@ -68,6 +69,18 @@ class VaisPromoForm extends ContentEntityForm {
$form = parent::buildForm($form, $form_state);
$entity = $this->entity;
$form['promo_content']['#states'] = [
'visible' => [
':input[name="promo_type"]' => ['value' => 'internal'],
],
];
$form['promo_link']['#states'] = [
'visible' => [
':input[name="promo_type"]' => ['value' => 'external'],
],
];
return $form;
}
......@@ -124,6 +137,28 @@ class VaisPromoForm extends ContentEntityForm {
}
// Validate referenced content (internal) or link (external) of promotion.
if ($form_state->getValue('promo_type')[0]['value'] == 'internal') {
if (empty($form_state->getValue('promo_content')[0]['target_id'])) {
$form_state->setErrorByName('promo_content',
$this->t('Reference a content item to be used by the promo.'));
}
}
elseif ($form_state->getValue('promo_type')[0]['value'] == 'external') {
if (empty($form_state->getValue('promo_link')[0]['value'])) {
$form_state->setErrorByName('promo_link',
$this->t('Specify an external URL to be used by the promo.'));
}
elseif (!UrlHelper::isValid($form_state->getValue('promo_link')[0]['value'], TRUE)) {
$form_state->setErrorByName('promo_link',
$this->t('Please provide a valid and full URL.'));
}
}
// Ensure numeric values.
if ($form_state->hasValue('weight') && !is_numeric($form_state->getValue('weight'))) {
$form_state->setErrorByName('weight', $this->t('Weight value must be numeric.'));
......@@ -146,6 +181,14 @@ class VaisPromoForm extends ContentEntityForm {
[['value' => strtolower($promoTrigger)]]
);
// Remove value for unneeded promo reference type.
if ($form_state->getValue('promo_type')[0]['value'] == 'external') {
$form_state->setValue('promo_content', [['target_id' => NULL]]);
}
elseif ($form_state->getValue('promo_type')[0]['value'] == 'internal') {
$form_state->setValue('promo_link', [['value' => NULL]]);
}
parent::submitForm($form, $form_state);
}
......
......@@ -4,6 +4,7 @@ namespace Drupal\vais_promos\Plugin\SearchResults;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\path_alias\AliasManagerInterface;
use Drupal\vertex_ai_search\Plugin\VertexSearchResultsPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -32,6 +33,13 @@ class PromotionSearchResults extends VertexSearchResultsPluginBase {
*/
protected $database;
/**
* Path Alias Manager.
*
* @var \Drupal\path_alias\AliasManagerInterface
*/
protected $aliasManager;
/**
* Constructor.
*
......@@ -45,6 +53,8 @@ class PromotionSearchResults extends VertexSearchResultsPluginBase {
* The Entity Type Manager service.
* @param \Drupal\Core\Database\Connection $database
* The database connection service.
* @param \Drupal\path_alias\AliasManagerInterface $aliasManager
* The path alias manager service.
*/
public function __construct(
array $configuration,
......@@ -52,10 +62,12 @@ class PromotionSearchResults extends VertexSearchResultsPluginBase {
array $plugin_definition,
EntityTypeManagerInterface $entityTypeManager,
Connection $database,
AliasManagerInterface $aliasManager,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->eTypeManager = $entityTypeManager;
$this->database = $database;
$this->aliasManager = $aliasManager;
}
/**
......@@ -67,7 +79,8 @@ class PromotionSearchResults extends VertexSearchResultsPluginBase {
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('database')
$container->get('database'),
$container->get('path_alias.manager')
);
}
......@@ -89,7 +102,7 @@ class PromotionSearchResults extends VertexSearchResultsPluginBase {
$triggerWords = explode(',', $result->trigger);
foreach ($triggerWords as $triggerWord) {
$promos[$triggerWord] = $result->pid;
$promos[trim($triggerWord)] = $result->pid;
}
}
......@@ -101,21 +114,27 @@ class PromotionSearchResults extends VertexSearchResultsPluginBase {
// Load the relevant promo.
$vaisPromo = $this->eTypeManager->getStorage('vais_promo')->load($promos[$keyword]);
$promoType = $vaisPromo->get('promo_type')->value;
// Load the promotion referenced content.
$promoContentId = $vaisPromo->get('promo_content')->target_id;
$vaisPromoContent = $this->eTypeManager->getStorage('node')->load($promoContentId);
// Set the promo reference to the external link.
$promoRef = $vaisPromo->get('promo_link')->value;
// Set the title.
$overrideTitle = $vaisPromo->get('promo_title_override')->value;
$promotionTitle = !empty($overrideTitle) ? $overrideTitle : $vaisPromoContent->getTitle();
// If the promotion uses referenced content, get the link.
if ($promoType == 'internal') {
// Load the promotion referenced content.
$promoContentId = $vaisPromo->get('promo_content')->target_id;
$promoRef = $this->aliasManager->getAliasByPath('/node/' . $promoContentId);
}
// Create the promotion result.
$promotion = [
'#theme' => 'vais_promos_promotion',
'#title' => $promotionTitle,
'#title' => $vaisPromo->get('promo_title_override')->value,
'#description' => $vaisPromo->get('promo_description')->value,
'#nid' => $vaisPromo->get('promo_content')->target_id,
'#promo_type' => $promoType,
'#href' => $promoRef,
'#term' => $keyword,
'#plugin_id' => $this->getPluginId(),
'#attached' => [
......
......@@ -8,6 +8,7 @@ use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -77,8 +78,9 @@ class VaisPromoListBuilder extends EntityListBuilder {
public function buildHeader() {
$header['promo_search_page'] = $this->t('Promotion Search Page');
$header['promo_trigger'] = $this->t('Promotion Trigger Query');
$header['promo_content'] = $this->t('Promotion Content');
$header['promo_title_override'] = $this->t('Promotion Title Override');
$header['promo_reference_type'] = $this->t('Promotion Reference Type');
$header['promo_reference_link'] = $this->t('Promotion Reference Link');
$header['promo_title_override'] = $this->t('Promotion Title');
$header['promo_description'] = $this->t('Promotion Description');
return $header + parent::buildHeader();
}
......@@ -90,15 +92,28 @@ class VaisPromoListBuilder extends EntityListBuilder {
$promoLink = Link::createFromRoute($entity->promo_trigger->value, 'entity.vais_promo.canonical', ['vais_promo' => $entity->id()]);
$promoContent = $this->entityTypeManager->getStorage('node')->load($entity->promo_content->target_id);
$promoContentLink = Link::createFromRoute($promoContent->label(), 'entity.node.canonical', ['node' => $entity->promo_content->target_id]);
$promoType = $entity->promo_type->value;
$promoReferenceType = $this->t('Internal');
$promoReferenceLink = NULL;
// Get link to referenced content; either internal node or external link.
if ($promoType == 'external') {
$promoReferenceUrl = Url::fromUri($entity->promo_link->value);
$promoReferenceType = $this->t('External');
$promoReferenceLink = Link::fromTextAndUrl($entity->promo_link->value, $promoReferenceUrl);
}
else {
$promoContent = $this->entityTypeManager->getStorage('node')->load($entity->promo_content->target_id);
$promoReferenceLink = Link::createFromRoute($promoContent->label(), 'entity.node.canonical', ['node' => $entity->promo_content->target_id]);
}
$searchPage = $this->entityTypeManager->getStorage('search_page')->load($entity->promo_search_page->value);
$searchPageLink = Link::createFromRoute($searchPage->label(), 'entity.search_page.edit_form', ['search_page' => $entity->promo_search_page->value]);
$row['promo_search_page'] = $searchPageLink;
$row['promo_trigger'] = $promoLink;
$row['promo_content'] = $promoContentLink;
$row['promo_reference_type'] = $promoReferenceType;
$row['promo_reference_link'] = $promoReferenceLink;
$row['promo_title_override'] = $entity->promo_title_override->value;
$row['promo_description'] = $entity->promo_description->value;
......
<div class="promotion">
<div class="title"><a href="/node/{{ nid }}">{{ title | raw }}</a></div>
<div class="title"><a href="{{ href }}">{{ title | raw }}</a></div>
<div class="description">{{ description | raw }}</div>
</div>
<?php
/**
* @file
* Vertex AI Search Promos installation file.
*/
use Drupal\Core\Field\BaseFieldDefinition;
/**
* Implements hook_update_N().
*
* Adds support for external url promotions.
*/
function vais_promos_update_100101(&$sandbox) {
$entityType = 'vais_promo';
$definitionManager = \Drupal::service('entity.definition_update_manager');
// Create promoted result external link field.
$newField = BaseFieldDefinition::create('string')
->setLabel(t('External Link'))
->setDescription(t('Provide the promoted result external link.'))
->setRequired(FALSE)
->setSettings([
'default_value' => '',
'max_length' => 255,
'text_processing' => 0,
])
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'string',
'weight' => -4,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -4,
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);
// Install the new definition.
$definitionManager->installFieldStorageDefinition('promo_link', $entityType, $entityType, $newField);
// Create Promoted Result Type Field.
$newField = BaseFieldDefinition::create('list_string')
->setLabel(t('Promoted Result Type'))
->setDescription(t('The type of Promoted Result.'))
->setRequired(TRUE)
->setSettings([
'allowed_values' => [
'internal' => t('Internal'),
'external' => t('External'),
],
])
->setDisplayOptions('view', [
'label' => 'visible',
'type' => 'list_default',
'weight' => -5,
])
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => -5,
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);
// Install the new definition.
$definitionManager->installFieldStorageDefinition('promo_type', $entityType, $entityType, $newField);
// Update existing 'promo_content' field settings.
$fieldDefinition = $definitionManager->getFieldStorageDefinition('promo_content', $entityType);
$fieldDefinition->setLabel(t('Content Reference'));
$fieldDefinition->setDescription(t('Reference the promoted content.'));
$fieldDefinition->setRequired(FALSE);
$definitionManager->updateFieldStorageDefinition($fieldDefinition);
// Update existing 'promo_title_override' field settings.
$fieldDefinition = $definitionManager->getFieldStorageDefinition('promo_title_override', $entityType);
$fieldDefinition->setLabel(t('Promotion Title'));
$fieldDefinition->setDescription(t('The displayed title of the promoted result.'));
$fieldDefinition->setRequired(TRUE);
$definitionManager->updateFieldStorageDefinition($fieldDefinition);
}
......@@ -63,7 +63,8 @@ function vais_promos_theme($existing, $type, $theme, $path) {
'variables' => [
'title' => NULL,
'description' => NULL,
'nid' => NULL,
'promo_type' => NULL,
'href' => NULL,
'term' => NULL,
],
'file' => 'vais_promos.theme.inc',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment