Skip to content

Commit

Permalink
Merge pull request #1264 from UN-OCHA/release-versions/v1.13.8
Browse files Browse the repository at this point in the history
release versions/v1.13.8
  • Loading branch information
berliner authored Dec 16, 2024
2 parents 8a3167c + 7d4bb5c commit 97fe4fd
Show file tree
Hide file tree
Showing 36 changed files with 470 additions and 110 deletions.
3 changes: 2 additions & 1 deletion composer.patches.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"patches": {
"drupal/core": {
"Issue #2820359: Add #element_submit and #limit_element_submit just like #element_validate and #limit_validation_errors": "https://www.drupal.org/files/issues/2024-09-04/2820359-121.patch",
"Issue #2844620: Automatically split headers into multiple lines when they exceed 8k": "https://www.drupal.org/files/issues/2024-12-02/automatically-split-headers-into-multiple-lines-when-they-exceed-8k-2844620.patch",
"Issue #3008924: Callers of LayoutEntityHelperTrait::getEntitySections() do not account for the view mode": "./patches/3008924-rerolled-24.patch",
"Issue #2902481: Add GROUP_CONCAT aggregate function to views": "https://www.drupal.org/files/issues/2024-08-09/add_group_concat_aggregate-2902481-44.patch",
"Issue #151311: Split 'administer permissions' into a new administer roles permissions": "https://www.drupal.org/files/issues/2023-01-19/split_administer_permissions_151311-72.patch",
Expand Down Expand Up @@ -58,7 +59,7 @@
"Issue #2958568: Add a search api processor for view unpublished": "./patches/2958568-view-unpublished-search-api-access-18.patch"
},
"drupal/webp": {
"Issue #3325808: Webp Image not generated for styles using original image.": "https://www.drupal.org/files/issues/2023-12-07/webp-3325808-11.patch",
"Issue #3325808: Webp Image not generated for styles using original image.": "https://git.drupalcode.org/project/webp/-/merge_requests/35.patch",
"Issue #3281606: Rendering duplicate images when the original images have the same name but different extension": "https://git.drupalcode.org/project/webp/-/merge_requests/30.patch",
"Issue #3153137: Using Image Widget Crop in responsive images does not refresh webp image": "./patches/3153137-custom-fix-3281606.patch"
}
Expand Down
6 changes: 3 additions & 3 deletions config_dev/stage_file_proxy.settings.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
_core:
default_config_hash: ttd8HXcqwSjGgp-fWA3gUA8q4TNvXB0a72pkFlnF56g
default_config_hash: LqXuXXQCTd1NWw7dGLef0PCi3_aEEWQuogAblo4hHaE
hotlink: false
origin: 'https://humanitarianaction.info'
origin: ''
origin_dir: sites/default/files
proxy_headers: ''
use_imagecache_root: true
verify: true
excluded_extensions: 'css,gz,js'
excluded_extensions: webp
108 changes: 108 additions & 0 deletions html/modules/custom/ghi_blocks/src/Helpers/AttachmentMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

namespace Drupal\ghi_blocks\Helpers;

use Drupal\ghi_plans\ApiObjects\AttachmentPrototype\AttachmentPrototype;
use Drupal\ghi_plans\ApiObjects\Attachments\AttachmentInterface;
use Drupal\ghi_plans\ApiObjects\Attachments\DataAttachment;

/**
* Helper function for attachment matching.
*/
class AttachmentMatcher {

/**
* Match an array of data attachments against an original attachment.
*
* This checks the attachment type and the attachment source to find
* attachments that correspond in their function.
*
* @param \Drupal\ghi_plans\ApiObjects\Attachments\DataAttachment $original_attachment
* The original attachment to match against.
* @param \Drupal\ghi_plans\ApiObjects\Attachments\DataAttachment[] $available_attachments
* The attachments to match.
*
* @return \Drupal\ghi_plans\ApiObjects\Attachments\DataAttachment[]
* The result set of matched attachments.
*/
public static function matchDataAttachments(AttachmentInterface $original_attachment, array $available_attachments) {
return array_filter($available_attachments, function (DataAttachment $attachment) use ($original_attachment) {
if ($original_attachment->getType() != $attachment->getType()) {
// Check the attachment type, e.g. "caseload" vs "indicator".
return FALSE;
}
if ($original_attachment->source->entity_type != $attachment->source->entity_type) {
// Check the source entity type, e.g. "governingEntity" vs "plan".
return FALSE;
}
if ($original_attachment->getPrototype()->getRefCode() != $attachment->getPrototype()->getRefCode()) {
// Check the attachment prototype ref code, e.g. "BP" vs "BF.
return FALSE;
}
return TRUE;
});
}

/**
* Match a data point index on the given attachments.
*
* Matching is done by type, such that a data point of attachment 2 is
* returned that has the same type as the given data point in attachment 1.
*
* @param int $data_point_index
* The data point index to match.
* @param \Drupal\ghi_plans\ApiObjects\Attachments\DataAttachment $attachment_1
* The first or original attachment.
* @param \Drupal\ghi_plans\ApiObjects\Attachments\DataAttachment $attachment_2
* The second or new attachment.
*
* @return int
* Either the original index if no match can be found or a new index.
*/
public static function matchDataPointOnAttachments($data_point_index, DataAttachment $attachment_1, DataAttachment $attachment_2) {
$prototype_1 = $attachment_1->getPrototype();
$prototype_2 = $attachment_2->getPrototype();
if (!$prototype_1 || !$prototype_2) {
return $data_point_index;
}
return self::matchDataPointOnAttachmentPrototypes($data_point_index, $prototype_1, $prototype_2);
}

/**
* Match a data point index on the given attachment prototypes.
*
* @param int $data_point_index
* The data point index to match.
* @param \Drupal\ghi_plans\ApiObjects\AttachmentPrototype\AttachmentPrototype $prototype_1
* The first or original attachment prototype.
* @param \Drupal\ghi_plans\ApiObjects\AttachmentPrototype\AttachmentPrototype $prototype_2
* The second or new attachment prototype.
*
* @return int
* Either the original index if no match can be found or a new index.
*/
public static function matchDataPointOnAttachmentPrototypes($data_point_index, AttachmentPrototype $prototype_1, AttachmentPrototype $prototype_2) {
// First get the original and the new fields. These are the types keyed by
// the field index.
$original_fields = $prototype_1->getFieldTypes();
$new_fields = $prototype_2->getFieldTypes();
if (!array_key_exists($data_point_index, $original_fields)) {
// This is fishy.
return $data_point_index;
}

// Compare the types.
if ($original_fields[$data_point_index] == ($new_fields[$data_point_index] ?? NULL)) {
// If they are the same, there is no need to go further.
return $data_point_index;
}
// It's referring to a different type now, let's see if we can find the
// same as the original type in the set of new fields.
$new_index = array_search($original_fields[$data_point_index], $new_fields);

// We either found a new index and can return it, or we didn't and we
// return the original.
return $new_index !== FALSE ? $new_index : $data_point_index;
}

}
22 changes: 12 additions & 10 deletions html/modules/custom/ghi_blocks/src/Plugin/Block/GHIBlockBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Markup;
use Drupal\Core\Url;
use Drupal\ghi_base_objects\Entity\BaseObjectAwareEntityInterface;
use Drupal\ghi_base_objects\Entity\BaseObjectInterface;
use Drupal\ghi_base_objects\Helpers\BaseObjectHelper;
use Drupal\ghi_blocks\Form\ImportBlockForm;
Expand Down Expand Up @@ -1584,19 +1585,19 @@ public function getPageNode() {
*/
public function getPageEntity($expected_class = ContentEntityInterface::class) {
$page_arguments = $this->getAllAvailablePageParameters();
$page_entity = NULL;
if (!empty($page_arguments['section_storage']) && $page_arguments['section_storage'] instanceof SectionStorageInterface) {
/** @var \Drupal\layout_builder\SectionStorageInterface $section_storage */
$section_storage = $page_arguments['section_storage'];
$section_contexts = array_keys($section_storage->getContexts());
$entity = in_array('entity', $section_contexts) ? $section_storage->getContextValue('entity') : NULL;
return $entity instanceof $expected_class ? $entity : NULL;
$page_entity = $entity instanceof $expected_class ? $entity : NULL;
}
if (!empty($page_arguments['node'])) {
return $page_arguments['node'];
}
if (!empty($page_arguments['node_from_original_id'])) {
return $page_arguments['node_from_original_id'];

if ($page_entity) {
return $page_entity;
}

foreach ($page_arguments as $page_argument) {
if (!$page_argument instanceof $expected_class) {
continue;
Expand Down Expand Up @@ -1659,11 +1660,12 @@ public function getCurrentBaseEntity($page_node = NULL) {
*/
public function getCurrentBaseObject($entity = NULL) {
$page_entity = $entity instanceof ContentEntityInterface ? $entity : $this->getPageEntity();
if ($page_entity && $page_entity->hasField('field_base_object')) {
return $page_entity->get('field_base_object')->entity;
if ($page_entity instanceof BaseObjectAwareEntityInterface) {
return $page_entity->getBaseObject();
}
elseif (($base_page = $this->getCurrentBaseEntity($page_entity)) && $base_page->hasField('field_base_object')) {
return $base_page->get('field_base_object')->entity;
$base_page = $this->getCurrentBaseEntity($page_entity);
if ($base_page instanceof BaseObjectAwareEntityInterface) {
return $base_page->getBaseObject();
}
$contexts = $this->getContexts();
foreach ($this->getContextMapping() as $context_name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -651,8 +651,8 @@ public function getConfigForm(array $form, FormStateInterface $form_state) {

$form['description'] = [
'#type' => 'markup',
'#markup' => $this->t('The following settings allow you to toggle some features for <em>this single map instance</em>. More <em>global settings</em>, that apply to various page elements across a year, can be controlled on the <a href="@url" target="_blank">GHI Global settings page</a>.', [
'@url' => Url::fromRoute('ghi_blocks.global_config', [], ['query' => ['year' => $this->getContextValue('year')]])->toString(),
'#markup' => $this->t('The following settings allow you to toggle some features for <em>this single map instance</em>. More <em>global settings</em>, that apply to various page elements across a year, can be controlled on the <a href=":url" target="_blank">GHI Global settings page</a>.', [
':url' => Url::fromRoute('ghi_blocks.global_config', [], ['query' => ['year' => $this->getContextValue('year')]])->toString(),
]),
];
$form['style'] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,8 @@ public function getConfigForm(array $form, FormStateInterface $form_state) {
$form['table'] = [
'#type' => 'details',
'#title' => $this->t('Table'),
'#description' => $this->t('The following settings allow you to toggle some features for <em>this single table instance</em>. More <em>global settings</em>, that apply to various page elements across a year, can be controlled on the <a href="@url" target="_blank">GHI Global settings page</a>.', [
'@url' => Url::fromRoute('ghi_blocks.global_config', [], ['query' => ['year' => $this->getContextValue('year')]])->toString(),
'#description' => $this->t('The following settings allow you to toggle some features for <em>this single table instance</em>. More <em>global settings</em>, that apply to various page elements across a year, can be controlled on the <a href=":url" target="_blank">GHI Global settings page</a>.', [
':url' => Url::fromRoute('ghi_blocks.global_config', [], ['query' => ['year' => $this->getContextValue('year')]])->toString(),
]),
'#tree' => TRUE,
'#group' => 'tabs',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\ghi_blocks\Helpers\AttachmentMatcher;
use Drupal\ghi_blocks\Interfaces\ConfigValidationInterface;
use Drupal\ghi_blocks\Interfaces\MultiStepFormBlockInterface;
use Drupal\ghi_blocks\Interfaces\OverrideDefaultTitleBlockInterface;
Expand Down Expand Up @@ -1201,11 +1202,12 @@ private function getAttachmentSwitcher() {
* An array with context data or query handlers.
*/
public function getBlockContext() {
$page_node = $this->getPageNode();
return [
'page_node' => $this->getPageNode(),
'page_node' => $page_node,
'plan_object' => $this->getCurrentPlanObject(),
'base_object' => $this->getCurrentBaseObject(),
'context_node' => $this->getPageNode(),
'context_node' => $page_node,
'attachment_prototype' => $this->getAttachmentPrototype(),
];
}
Expand Down Expand Up @@ -1329,7 +1331,7 @@ public function fixConfigErrors() {
if (!$attachment instanceof DataAttachment) {
continue;
}
$filtered_attachments = $this->matchDataAttachments($attachment, $available_attachments);
$filtered_attachments = AttachmentMatcher::matchDataAttachments($attachment, $available_attachments);
foreach ($filtered_attachments as $filtered_attachment) {
$conf['attachments']['entity_attachments']['attachments']['attachment_id'][$filtered_attachment->id()] = $filtered_attachment->id();
$conf['attachments']['entity_attachments']['entities']['entity_ids'][$filtered_attachment->source->entity_id] = $filtered_attachment->source->entity_id;
Expand All @@ -1338,8 +1340,14 @@ public function fixConfigErrors() {
}
}

$default_attachment = array_key_first($conf['attachments']['entity_attachments']['attachments']['attachment_id']);
$conf['map']['common']['default_attachment'] = $default_attachment;
// Check the configured default attachment.
$default_attachment = $conf['map']['common']['default_attachment'] ?? NULL;
$attachment_ids = $conf['attachments']['entity_attachments']['attachments']['attachment_id'] ?? [];
if ($default_attachment && !array_key_exists($default_attachment, $attachment_ids)) {
// Just unset the default attachment, so that the rendering can decide
// which one to use.
$conf['map']['common']['default_attachment'] = NULL;
}

$this->setBlockConfig($conf);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,12 +730,13 @@ public function getBlockContext() {
// This can be any parent node, e.g. SectionNode or PlanClusterNode.
$base_entity = $this->getCurrentBaseEntity();
$section_node = $this->sectionManager->getCurrentSection($base_entity);
$page_node = $this->getPageNode();
return [
'section_node' => $section_node,
'page_node' => $this->getPageNode(),
'page_node' => $page_node,
'plan_object' => $plan_object,
'base_object' => $this->getCurrentBaseObject(),
'context_node' => $this->getPageNode(),
'context_node' => $page_node,
'entities' => $plan_entities,
'entity_types' => $this->logframeManager->getEntityTypesFromPlanObject($plan_object),
'attachment_prototypes' => $this->getAttachmentPrototypes(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\ghi_base_objects\Helpers\BaseObjectHelper;
use Drupal\ghi_blocks\Helpers\AttachmentMatcher;
use Drupal\ghi_blocks\Interfaces\AttachmentTableInterface;
use Drupal\ghi_blocks\Interfaces\ConfigValidationInterface;
use Drupal\ghi_blocks\Interfaces\ConfigurableTableBlockInterface;
Expand Down Expand Up @@ -556,10 +557,33 @@ public function getConfigErrors() {
*/
public function fixConfigErrors() {
$conf = $this->getBlockConfig();
$original_prototype_id = $conf['base']['prototype_id'] ?? NULL;
$prototype_options = $this->getUniquePrototypeOptions();
if (count($prototype_options) == 1) {
$conf['base']['prototype_id'] = array_key_first($prototype_options);
}
if ($original_prototype_id && !empty($conf['base']['prototype_id'])) {
$new_prototype_id = $conf['base']['prototype_id'];
/** @var \Drupal\ghi_plans\Plugin\EndpointQuery\AttachmentPrototypeQuery $query */
$query = $this->endpointQueryManager->createInstance('attachment_prototype_query');
$original_prototype = $query->getPrototypeById($original_prototype_id);
$new_prototype = $query->getPrototypeById($new_prototype_id);
foreach ($conf['table']['columns'] as &$column) {
if ($column['item_type'] == 'data_point') {
$data_points = &$column['config']['data_point']['data_points'];
$data_points[0]['index'] = AttachmentMatcher::matchDataPointOnAttachmentPrototypes($data_points[0]['index'], $original_prototype, $new_prototype);
if ($column['config']['data_point']['processing'] != 'single') {
$data_points[1]['index'] = AttachmentMatcher::matchDataPointOnAttachmentPrototypes($data_points[1]['index'], $original_prototype, $new_prototype);
}
}
if ($column['item_type'] == 'spark_line_chart') {
$column['config']['data_point'] = AttachmentMatcher::matchDataPointOnAttachmentPrototypes($column['config']['data_point'], $original_prototype, $new_prototype);
if ($column['config']['show_baseline']) {
$column['config']['baseline'] = AttachmentMatcher::matchDataPointOnAttachmentPrototypes($column['config']['baseline'], $original_prototype, $new_prototype);
}
}
}
}
$this->setBlockConfig($conf);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\ghi_blocks\Helpers\AttachmentMatcher;
use Drupal\ghi_blocks\Traits\PlanFootnoteTrait;
use Drupal\ghi_form_elements\ConfigurationContainerItemPluginBase;
use Drupal\ghi_plans\Entity\Plan;
Expand Down Expand Up @@ -232,33 +233,45 @@ public function getConfigurationErrors() {
* {@inheritdoc}
*/
public function fixConfigurationErrors() {
$conf = $this->config['attachment'];
$attachment = $this->getAttachmentObject();
$conf = &$this->config;
$attachment_id = &$conf['attachment']['attachment_id'];
$original_attachment = $this->getAttachmentObject();

/** @var \Drupal\ghi_plans\Entity\Plan $plan */
$plan = $this->getContextValue('plan_object');
if ($attachment && $plan && $attachment->getPlanId() != $plan->getSourceId()) {
$conf['attachment_id'] = NULL;
if ($original_attachment && $plan && $original_attachment->getPlanId() != $plan->getSourceId()) {
$attachment_id = NULL;
}

if ($attachment) {
if ($original_attachment) {
// Let's see if we can find an alternative attachment.
/** @var \Drupal\ghi_plans\Plugin\EndpointQuery\PlanEntitiesQuery $query */
$query = $this->endpointQueryManager->createInstance('plan_entities_query');
$query->setPlaceholder('plan_id', $plan->getSourceId());
$attachments = $query->getDataAttachments($this->getContextValue('base_object'));
$filtered_attachments = $this->matchDataAttachments($attachment, $attachments);
$filtered_attachments = AttachmentMatcher::matchDataAttachments($original_attachment, $attachments);

// Use the default plan caseload if available.
$caseload_id = $plan->getPlanCaseloadId();
if ($caseload_id && $attachment->getType() == 'caseload' && array_key_exists($caseload_id, $filtered_attachments)) {
$conf['attachment_id'] = $caseload_id;
if ($caseload_id && $original_attachment->getType() == 'caseload' && array_key_exists($caseload_id, $filtered_attachments)) {
$attachment_id = $caseload_id;
}
elseif (count($filtered_attachments) == 1) {
$conf['attachment_id'] = array_key_first($filtered_attachments);
$attachment_id = array_key_first($filtered_attachments);
}
}

$this->config['attachment'] = $conf;
if (!empty($attachment_id)) {
// Lets see if we can assure that the data points are properly translated
// if needed.
$new_attachment = $filtered_attachments[$attachment_id];
$data_point_conf = &$this->config['data_point'];
$data_points = &$data_point_conf['data_points'];
$data_points[0]['index'] = AttachmentMatcher::matchDataPointOnAttachments($data_points[0]['index'], $original_attachment, $new_attachment);
if ($data_point_conf['processing'] != 'single') {
$data_points[1]['index'] = AttachmentMatcher::matchDataPointOnAttachments($data_points[1]['index'], $original_attachment, $new_attachment);
}
}
}

}
Loading

0 comments on commit 97fe4fd

Please sign in to comment.