Skip to content

Commit

Permalink
Merge pull request #258 from wri/issue-12-narr-tax
Browse files Browse the repository at this point in the history
Issue 12 narr tax
  • Loading branch information
mariacha authored Sep 17, 2024
2 parents 14202d9 + 32b105a commit d0a5fbc
Show file tree
Hide file tree
Showing 13 changed files with 501 additions and 69 deletions.
194 changes: 154 additions & 40 deletions modules/wri_common/wri_common.module
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,18 @@ function wri_common_token_info() {
'name' => 'A node link',
'description' => 'The link to the node, if published, or its title if not.',
];
$info['tokens']['node']['projects_links'] = [
'name' => 'A listing of project links',
'description' => 'The link to the related projects if published, and nothing if not.',
];
$info['tokens']['node']['projects_links_within'] = [
'name' => 'A listing of project links, followed by "within"',
'description' => 'The link to the related projects if published, and the site title if no projects are related.',
];
$info['tokens']['node']['primary_contact_links'] = [
'name' => 'The primary contact link or a fallback phrase.',
'description' => 'The link to the related primary contact if published, and a fallback phrase if no published contact found.',
];
$info['tokens']['taxonomy_term']['link'] = [
'name' => 'A term link',
'description' => 'The link to the term, if published, or its title if not.',
Expand Down Expand Up @@ -211,7 +223,28 @@ function wri_common_tokens($type, $tokens, array $data, array $options, Bubbleab

case 'topic_and_sub_topic_links_list':
$terms = wri_common_get_node_topics($node, FALSE);
$replacements[$original] = _wri_common_format_list($terms);
// If the node has a topic whose Landing page points to a value in
// Project, filter that out.
if ($terms && $node->hasField('field_projects') && ($projects = $node->get('field_projects')) && !$projects->isEmpty()) {
$project_items = [];
$allowed_terms = [];
foreach ($projects->getValue() as $value) {
$project_items[] = $value['target_id'];
}
foreach ($terms as $term) {
if (!in_array($term->field_landing_page->target_id, $project_items)) {
$allowed_terms[] = $term;
}
}
$terms = $allowed_terms;
}

if (empty($terms)) {
$replacements[$original] = \Drupal::config('system.site')->get('name');
}
else {
$replacements[$original] = _wri_common_format_list($terms);
}
break;

case 'sub_topic_links_list':
Expand All @@ -234,6 +267,44 @@ function wri_common_tokens($type, $tokens, array $data, array $options, Bubbleab
switch ($name) {
case 'link':
$replacements[$original] = wri_common_link_or_text($data['node']);
break;

case 'projects_links':
if ($node->hasField('field_projects') && ($projects = $node->get('field_projects')->referencedEntities())) {
$published_projects = [];
foreach ($projects as $project) {
if ($project->isPublished()) {
$published_projects[] = $project;
}
}

$replacements[$original] = _wri_common_format_list($published_projects);
}
break;

case 'projects_links_within':
// Get the projects_links value using tokens.
$phrase = \Drupal::config('wri_node.settings')->get('within_phrase');
$replaced = \Drupal::token()->replace('[node:projects_links]', ['node' => $node], ['clear' => TRUE]);
if ($replaced) {
$replacements[$original] = Markup::create((str_replace('[node:projects_links_within]', $replaced, $phrase) . ' '));
}
break;

case 'primary_contact_links':
if ($node->hasField('field_primary_contacts') && ($contact_items = $node->get('field_primary_contacts')) && !$contact_items->isEmpty()) {
$contact_item = $contact_items->first()->entity;
if ($contact_item) {
$replacements[$original] = wri_common_link_or_text($contact_item, $node);
}
else {
$replacements[$original] = wri_common_person_link_fallback($node);
}
}
else {
$replacements[$original] = wri_common_person_link_fallback($node);
}
break;
}
}
}
Expand Down Expand Up @@ -265,19 +336,20 @@ function wri_common_tokens($type, $tokens, array $data, array $options, Bubbleab
*/
function wri_common_get_node_topics(Node $node, $secondary_only = FALSE) {
$topics = [];
if (!$secondary_only && $node->hasField('field_primary_topic') && ($topic_items = $node->get('field_primary_topic')) && !$topic_items->isEmpty()) {
$topic_item = $topic_items->first()->entity;
if ($topic_item && $topic_item->isPublished()) {
$topics[] = $topic_item;
}
$existing_topics = [];
if (!$secondary_only && $node->hasField('field_primary_topic') && ($topic_items = $node->get('field_primary_topic')) && !$topic_items->isEmpty() && $topic_items->first()->entity) {
$topics[] = $topic_items->first()->entity;
$existing_topics[$topic_items->first()->entity->id()] = TRUE;
}
if ($node->hasField('field_tags') && ($tag_items = $node->get('field_tags')) && !$tag_items->isEmpty()) {
foreach ($tag_items as $tag_item) {
if (isset($tag_item->entity) && $tag_item->entity->bundle() == 'topics_and_subtopics' && $tag_item->entity->isPublished()) {
if (isset($tag_item->entity) && $tag_item->entity->bundle() == 'topics_and_subtopics' && $tag_item->entity->isPublished() && !isset($existing_topics[$tag_item->entity->id()])) {
$topics[] = $tag_item->entity;
$existing_topics[$tag_item->entity->id()] = TRUE;
}
}
}

return $topics;
}

Expand Down Expand Up @@ -321,23 +393,32 @@ function _wri_common_format_list(array $terms) {
$list = '';
if ($terms) {
foreach ($terms as $term) {
$term_url = $term->toUrl();
if ($term->hasField('field_full_name') && $term_label = $term->get('field_full_name')->getString()) {
if ($term_url->toString()) {
$term_name = Link::fromTextAndUrl($term_label, $term_url)
->toRenderable();
$renderer = \Drupal::service('renderer');
$term_name = $renderer->render($term_name);
$published = $term->isPublished();
if ($published) {
$term_url = $term->toUrl();
if ($term->hasField('field_full_name') && $term_label = $term->get('field_full_name')->getString()) {
if ($term_url->toString()) {
$term_name = Link::fromTextAndUrl($term_label, $term_url)
->toRenderable();
$renderer = \Drupal::service('renderer');
$term_name = $renderer->render($term_name);
}
}
else {
$term_name = $term->toLink()->tostring();
}
}
else {
$term_name = $term->toLink()->tostring();
$term_name = $term->label();
}

// If there is more than 1 term, build a list.
if (count($terms) > 1) {
if (!next($terms)) {
$list .= "and $term_name";
// Put no comma between A and B, remove Oxford comma.
$list = trim($list, ', ') . ' ';
// Leave the Oxford comma, A, B, and C.
$list .= \Drupal::config('wri_node.settings')->get('and_phrase') . " $term_name";
}
else {
$list .= "$term_name, ";
Expand All @@ -358,40 +439,21 @@ function _wri_common_format_list(array $terms) {
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\node\Entity\NodeInterface $node
* The node that this entity is appearing on, if not the same as the entity.
*
* @return string
* A string representing the entity with or without a link.
*/
function wri_common_link_or_text(EntityInterface $entity) {
function wri_common_link_or_text(EntityInterface $entity, NodeInterface $node = NULL) {
$link = '';
if (isset($entity)) {
if ($entity->isPublished()) {
$link = $entity->toLink()->toString();
}
else {
if ($entity->bundle() == 'person') {
$url = Url::fromUserInput(\Drupal::config('wri_node.settings')->get('person_listing_url'));

// See if the current page is a node.
$node = \Drupal::routeMatch()->getParameter('node');
if ($node instanceof NodeInterface) {
// If the current page is a project, link to its experts page.
if ($node->bundle() == 'project_detail') {
$url = Url::fromUserInput('/project-experts/' . $node->id());
}
// Otherwise, see if that node has a 'field_projects', and THAT node
// is published.
elseif ($node->hasField('field_projects')) {
$project = $node->field_projects->entity;
if ($project && $project->isPublished()) {
// If it is, link to the projects/experts page.
$url = Url::fromUserInput('/project-experts/' . $node->field_projects->target_id);
}
}
}

// Fallback to the /about/experts page.
$link = Link::fromTextAndUrl(\Drupal::config('wri_node.settings')->get('unpublished_person_phrase'), $url)->toString();
if ($entity->bundle() == 'person' && $node) {
$link = wri_common_person_link_fallback($node);
}
else {
$link = $entity->label();
Expand All @@ -401,6 +463,58 @@ function wri_common_link_or_text(EntityInterface $entity) {
return $link;
}

/**
* Fallback for when a person is unpublished.
*
* @param \Drupal\Core\Entity\EntityInterface $node
* The person node.
*
* @return \Drupal\Core\GeneratedLink
* The link.
*/
function wri_common_person_link_fallback(EntityInterface $node) {
$url = wri_common_url_from_node_project($node);

if (!$url) {
$url = Url::fromUserInput(\Drupal::config('wri_node.settings')
->get('person_listing_url'));
}

// Fallback to the /about/experts page.
$link = Link::fromTextAndUrl(\Drupal::config('wri_node.settings')->get('unpublished_person_phrase'), $url)->toString();

return $link;
}

/**
* Get the URL for a project from a node.
*
* @param \Drupal\Core\Entity\EntityInterface $node
* The node.
*
* @return \Drupal\Core\Url|false\
* The url, or false if no url could be produced.
*/
function wri_common_url_from_node_project($node) {
$url = FALSE;
if ($node instanceof NodeInterface) {
// If the current page is a project, link to its experts page.
if ($node->bundle() == 'project_detail') {
$url = Url::fromUserInput('/project-experts/' . $node->id());
}
// Otherwise, see if that node has a 'field_projects', and THAT node
// is published.
elseif ($node->hasField('field_projects')) {
$project = $node->field_projects->entity;
if ($project && $project->isPublished()) {
// If it is, link to the projects/experts page.
$url = Url::fromUserInput('/project-experts/' . $node->field_projects->target_id);
}
}
}
return $url;
}

/**
* Implements hook_page_attachments_alter().
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ field_name: field_narrative_taxonomy
entity_type: node
bundle: data
label: 'Narrative Taxonomy'
description: 'If you want to use the default value, choose "Source" and paste: <code>&lt;p&gt;This &#91;node:field_type:entity&#93; is part of the &#91;node:field_projects:entity:link&#93; within our &#91;wri_tokens:topic_and_sub_topic_links_list&#93;. Reach out to &#91;node:field_primary_contacts:entity:link&#93; for more information.&lt;/p&gt;</code>'
description: 'If you want to use the default value, choose "Source" and paste: <code>&lt;p&gt;This &#91;node:field_type:entity&#93; is part of the &#91;node:projects_links_within&#93; our &#91;wri_tokens:topic_and_sub_topic_links_list&#93;. Reach out to &#91;node:primary_contact_links&#93; for more information.&lt;/p&gt;</code>'
required: false
translatable: true
default_value:
-
value: "<p>This [node:field_type:entity] is part of the [node:field_projects:entity:link] within our [wri_tokens:topic_and_sub_topic_links_list]. Reach out to [node:field_primary_contacts:entity:link] for more information.</p>\r\n"
value: "<p>This [node:field_type:entity] is part of the [node:projects_links_within] our [wri_tokens:topic_and_sub_topic_links_list]. Reach out to [node:primary_contact_links] for more information.</p>\r\n"
format: basic_html
default_value_callback: ''
settings: { }
Expand Down
72 changes: 70 additions & 2 deletions modules/wri_narrative/wri_narrative.post_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ function wri_narrative_post_update_rewrite_narrative_taxonomies(&$sandbox) {
'<a href="/node/[node:field_primary_contacts:target_id]">[node:field_primary_contacts:entity]</a>',
'<a href="/node/[node:field_featured_experts:target_id]">[node:field_featured_experts:entity]</a>',
],
['[node:field_projects:entity:link]',
'[node:field_primary_contacts:entity:link]',
['[node:projects_links]',
'[node:primary_contact_links]',
'[node:field_featured_experts:entity:link]',
],
$taxonomy_value[0]['value']
Expand All @@ -71,3 +71,71 @@ function wri_narrative_post_update_rewrite_narrative_taxonomies(&$sandbox) {

$sandbox['#finished'] = ($sandbox['current'] == $start_value);
}

/**
* Updates the tokens in narrative taxonomies, round 2.
*/
function wri_narrative_post_update_rewrite_narrative_taxonomies3(&$sandbox) {
// We don't display the narrative taxonomy on nodes older than 2020, so clear
// that boilerplate out of the database.
Drupal::database()->query("DELETE FROM node__field_narrative_taxonomy WHERE entity_id IN (SELECT nid FROM node_field_data WHERE created<1577836800 AND type IN ('data', 'publication'))")->execute();
Drupal::database()->query("DELETE FROM node_revision__field_narrative_taxonomy WHERE entity_id IN (SELECT nid FROM node_field_data WHERE created<1577836800 AND type IN ('data', 'publication'))")->execute();

if (!isset($sandbox['total'])) {
$sandbox['total'] = Drupal::database()->select('node__field_narrative_taxonomy', 'u')
->condition('u.field_narrative_taxonomy_value', '[node:field_(projects|primary_contacts):entity:link]', 'REGEXP')
->fields('u')
->countQuery()
->execute()
->fetchField();
$sandbox['current'] = 0;

if (empty($sandbox['total'])) {
$sandbox['#finished'] = 1;
return;
}
}

$users_per_batch = 25;
$start_value = $sandbox['current'];
$nids = Drupal::database()->select('node__field_narrative_taxonomy', 'u')
->condition('u.field_narrative_taxonomy_value', '\[node:field_(projects|primary_contacts):entity:link\]', 'REGEXP')
->condition('entity_id', $sandbox['current'], '>=')
->fields('u')
->orderBy('entity_id')
->range(0, $users_per_batch)
->execute();

if (empty($nids)) {
$sandbox['#finished'] = 1;
return;
}
// Loop through each node.
foreach ($nids as $result) {
$node = Node::load($result->entity_id);
if ($node->hasTranslation($result->langcode)) {
$node = $node->getTranslation($result->langcode);
}
$taxonomy_value = $node->field_narrative_taxonomy->getValue();
// Replace link strings with new values.
$taxonomy_value[0]['value'] = str_replace(
['[node:field_primary_contacts:entity:link]',
'[node:field_projects:entity:link] within ',
],
['[node:primary_contact_links]',
'[node:projects_links_within]',
],
$taxonomy_value[0]['value']
);
$node->field_narrative_taxonomy->setValue($taxonomy_value);

// Save the node.
$node->save();
$sandbox['current'] = $result->entity_id;
}

\Drupal::messenger()
->addMessage($sandbox['current'] . ' node last processed.');

$sandbox['#finished'] = ($sandbox['current'] == $start_value);
}
7 changes: 7 additions & 0 deletions modules/wri_node/config/schema/wri_node.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ wri_node.settings:
twitter_share_suffix:
type: text
label: 'Twitter Share suffix'
and_phrase:
type: text
label: 'And word for listings, ie: 1, 2 "and" 3'
within_phrase:
type: text
label: 'And word for "within" in the phrase "is part of X-project within Y-topic"'

Loading

0 comments on commit d0a5fbc

Please sign in to comment.