Commit 17986a84 authored by Chris Shantz's avatar Chris Shantz
Browse files

Merge branch '1.0.x' into prod/1.0.x

parents dc139c54 3d310872
backend: pdftk
allowed_schemes:
- private
template_scheme: private
......@@ -3,31 +3,26 @@ uw_global_header.admissions:
menu_name: uw-menu-global-header
url: https://uwaterloo.ca/admissions/
weight: 1
uw_global_header.about_waterloo:
title: 'About Waterloo'
menu_name: uw-menu-global-header
url: https://uwaterloo.ca/about/
weight: 2
uw_global_header.faculties_academics:
title: 'Faculties & academics'
menu_name: uw-menu-global-header
url: https://uwaterloo.ca/faculties-academics/
weight: 3
uw_global_header.offices_services:
title: 'Offices & services'
menu_name: uw-menu-global-header
url: https://uwaterloo.ca/offices-services/
weight: 4
uw_global_header.support_waterloo:
title: 'Support Waterloo'
menu_name: uw-menu-global-header
url: https://uwaterloo.ca/support/
weight: 5
uw_global_header.covid_19:
title: 'COVID-19'
menu_name: uw-menu-global-header
......@@ -39,49 +34,41 @@ uw_global_footer.contact_waterloo:
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/about/contact-us
weight: 1
uw_global_footer.accessibility:
title: 'Accessibility'
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/accessibility/
weight: 2
uw_global_footer.media:
title: 'News'
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/news/
weight: 3
uw_global_footer.maps_directions:
title: 'Maps & directions'
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/map/
weight: 4
uw_global_footer.privacy:
title: 'Privacy'
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/privacy/
weight: 5
uw_global_footer.careers:
title: 'Careers'
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/careers/
weight: 6
uw_global_footer.watsafe:
title: 'Watsafe'
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/watsafe/
weight: 7
uw_global_footer.copyright:
title: 'Copyright'
menu_name: uw-menu-global-footer
url: https://uwaterloo.ca/copyright
weight: 8
uw_global_footer.feedback:
title: 'Feedback'
menu_name: uw-menu-global-footer
......@@ -93,25 +80,21 @@ uw_global_social_media.facebook:
menu_name: uw-menu-global-social-media
url: https://www.facebook.com/university.waterloo
weight: 1
uw_global_social_media.twitter:
title: 'Twitter'
menu_name: uw-menu-global-social-media
url: https://twitter.com/uWaterloo
weight: 2
uw_global_social_media.youtube:
title: 'YouTube'
menu_name: uw-menu-global-social-media
url: https://www.youtube.com/user/uwaterloo
weight: 3
uw_global_social_media.instagram:
title: 'Instagram'
menu_name: uw-menu-global-social-media
url: https://www.instagram.com/uofwaterloo/
weight: 4
uw_global_social_media.linkedin:
title: 'LinkedIn'
menu_name: uw-menu-global-social-media
......@@ -123,229 +106,191 @@ uw_content_management.content_types:
menu_name: uw-menu-content-management
url: internal:/dashboard/my_dashboard
weight: 0
uw_content_management.content_types.blog_post:
title: 'Blog post'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_blog
weight: 0
uw_content_management.content_types.catalog_item.add_blog_tag:
title: 'Add blog tag'
parent: uw_content_management.content_types.blog_post
url: internal:/admin/structure/taxonomy/manage/uw_vocab_blog_tags/add
weight: 0
uw_content_management.content_types.catalog_item.list_blog_tag:
title: 'List blog tags'
parent: uw_content_management.content_types.blog_post
url: internal:/admin/structure/taxonomy/manage/uw_vocab_blog_tags/overview
weight: 0
uw_content_management.content_types.catalog_item:
title: 'Catalog item'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_catalog_item
weight: 0
uw_content_management.content_types.catalog_item.add_catalog:
title: 'Add catalog'
parent: uw_content_management.content_types.catalog_item
url: internal:/admin/structure/taxonomy/manage/uw_vocab_catalogs/add
weight: 0
uw_content_management.content_types.catalog_item.list_catalogs:
title: 'List catalogs'
parent: uw_content_management.content_types.catalog_item
url: internal:/admin/structure/taxonomy/manage/uw_vocab_catalogs/overview
weight: 0
uw_content_management.content_types.catalog_item.add_catalog_category:
title: 'Add catalog category'
parent: uw_content_management.content_types.catalog_item
url: internal:/admin/structure/taxonomy/manage/uw_vocab_catalog_categories/add
weight: 0
uw_content_management.content_types.catalog_item.list_catalog_categories:
title: 'List catalog categories'
parent: uw_content_management.content_types.catalog_item
url: internal:/admin/structure/taxonomy/manage/uw_vocab_catalog_categories/overview
weight: 0
uw_content_management.content_types.contact:
title: 'Contact'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_contact
weight: 0
uw_content_management.content_types.contact.rearrange:
title: 'Rearrange'
parent: uw_content_management.content_types.contact
url: internal:/admin/rearrange-contacts
weight: 0
uw_content_management.content_types.contact:.add_contact_tag:
title: 'Add contact tag'
parent: uw_content_management.content_types.contact
url: internal:/admin/structure/taxonomy/manage/uw_vocab_contact_group/add
weight: 1
uw_content_management.content_types.contact.list_contact_tag:
title: 'List contact tags'
parent: uw_content_management.content_types.contact
url: internal:/admin/structure/taxonomy/manage/uw_vocab_contact_group/overview
weight: 2
uw_content_management.content_types.event:
title: 'Event'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_event
weight: 0
uw_content_management.content_types.event.add_event_tag:
title: 'Add event tag'
parent: uw_content_management.content_types.event
url: internal:/admin/structure/taxonomy/manage/uw_tax_event_tags/add
weight: 0
uw_content_management.content_types.event.list_event_tags:
title: 'List event tags'
parent: uw_content_management.content_types.event
url: internal:/admin/structure/taxonomy/manage/uw_tax_event_tags/overview
weight: 0
uw_content_management.content_types.event.add_event_type:
title: 'Add event type'
parent: uw_content_management.content_types.event
url: internal:/admin/structure/taxonomy/manage/uw_tax_event_type/add
weight: 0
uw_content_management.content_types.event.list_event_types:
title: 'List event types'
parent: uw_content_management.content_types.event
url: internal:/admin/structure/taxonomy/manage/uw_tax_event_type/overview
weight: 0
uw_content_management.content_types.expand_collapse:
title: 'Expand/collapse group'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_expand_collapse_group
weight: 0
uw_content_management.content_types.news_item:
title: 'News item'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_news_item
weight: 0
uw_content_management.content_types.news_item.add_news_tag:
title: 'Add news tag'
parent: uw_content_management.content_types.news_item
url: internal:/admin/structure/taxonomy/manage/uw_vocab_news_tags/add
weight: 0
uw_content_management.content_types.news_item.list_news_tags:
title: 'List news tags'
parent: uw_content_management.content_types.news_item
url: internal:/admin/structure/taxonomy/manage/uw_vocab_news_tags/overview
weight: 0
uw_content_management.content_types.opportunity:
title: 'Opportunity'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_opportunity
weight: 0
uw_content_management.content_types.profile:
title: 'Profile'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_profile
weight: 0
uw_content_management.content_types.profile.rearrange:
title: 'Rearrange'
parent: uw_content_management.content_types.profile
url: internal:/admin/rearrange-profiles
weight: 0
uw_content_management.content_types.profile.add_profile_type:
title: 'Add profile type'
parent: uw_content_management.content_types.profile
url: internal:/admin/structure/taxonomy/manage/uw_vocab_profile_type/add
weight: 1
uw_content_management.content_types.profile.list_profile_types:
title: 'List profile types'
parent: uw_content_management.content_types.profile
url: internal:/admin/structure/taxonomy/manage/uw_vocab_profile_type/overview
weight: 2
uw_content_management.content_types.projects:
title: 'Projects'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_project
weight: 0
uw_content_management.content_types.projects.add_project_role:
title: 'Add project role'
parent: uw_content_management.content_types.projects
url: internal:/admin/structure/taxonomy/manage/uw_vocab_project_role/add
weight: 0
uw_content_management.content_types.projects.add_project_topic:
title: 'Add project topic'
parent: uw_content_management.content_types.projects
url: internal:/admin/structure/taxonomy/manage/uw_vocab_project_topic/add
weight: 0
uw_content_management.content_types.projects.list_project_roles:
title: 'List project roles'
parent: uw_content_management.content_types.projects
url: internal:/admin/structure/taxonomy/manage/uw_vocab_project_role/overview
weight: 0
uw_content_management.content_types.projects.list_project_topics:
title: 'List project topics'
parent: uw_content_management.content_types.projects
url: internal:/admin/structure/taxonomy/manage/uw_vocab_project_topic/overview
weight: 0
uw_content_management.content_types.service:
title: 'Service'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_service
weight: 0
uw_content_management.content_types.service.add_service_category:
title: 'Add service category'
parent: uw_content_management.content_types.service
url: internal:/admin/structure/taxonomy/manage/uw_vocab_service_categories/add
weight: 0
uw_content_management.content_types.service.list_service_categories:
title: 'List service categories'
parent: uw_content_management.content_types.service
url: internal:/admin/structure/taxonomy/manage/uw_vocab_service_categories/overview
weight: 0
uw_content_management.content_types.sidebar:
title: 'Sidebar'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_sidebar
weight: 0
uw_content_management.content_types.site_footer:
title: 'Site footer'
parent: uw_content_management.content_types
url: internal:/node/add/uw_ct_site_footer
weight: 0
uw_content_management.content_types.special_alert:
title: 'Special alert'
parent: uw_content_management.content_types
route_name: uw_custom_blocks.special_alert.settings
weight: 0
uw_content_management.content_types.web_page:
title: 'Web page'
parent: uw_content_management.content_types
......@@ -357,37 +302,37 @@ uw_content_management.forms:
menu_name: uw-menu-content-management
url: internal:/dashboard/my_dashboard
weight: 0
uw_content_management.forms.form:
title: 'Form'
parent: uw_content_management.forms
url: internal:/admin/structure/webform/add
weight: 0
uw_content_management.forms.form.manage_submissions:
title: 'Manage submissions'
parent: uw_content_management.forms.form
url: internal:/admin/structure/webform/submissions/manage
weight: 0
uw_content_management.forms.form.fillpdf.forms_admin:
title: 'Manage PDFs'
parent: uw_content_management.forms.form
route_name: fillpdf.forms_admin
weight: 1
uw_content_management.global_vocabularies:
title: 'Global vocabularies'
menu_name: uw-menu-content-management
url: internal:/dashboard/my_dashboard
weight: 0
uw_content_management.global_vocabularies.audience:
title: 'Audience'
parent: uw_content_management.global_vocabularies
url: internal:/admin/structure/taxonomy/manage/uw_vocab_audience/add
weight: 0
uw_content_management.global_vocabularies.audience.list_term:
title: 'List terms'
parent: uw_content_management.global_vocabularies.audience
url: internal:/admin/structure/taxonomy/manage/uw_vocab_audience/overview
weight: 0
uw_content_management.global_vocabularies.audience.manage:
title: 'Manage'
parent: uw_content_management.global_vocabularies.audience
......@@ -399,49 +344,41 @@ uw_site_management.content_access:
menu_name: uw-menu-site-management
url: internal:/admin/content-access
weight: 0
uw_site_management.fix_404_pages:
title: 'Fix 404 pages'
menu_name: uw-menu-site-management
url: internal:/admin/config/search/redirect/404
weight: 0
uw_site_management.ofis:
title: 'OFIS settings'
menu_name: uw-menu-site-management
route_name: uw_ws_ofis.settings_form
weight: 0
uw_site_management.menus:
title: 'Menus'
menu_name: uw-menu-site-management
route_name: entity.menu.collection
weight: 0
uw_site_management.google_analytics:
title: 'Google Analytics and site ownership'
menu_name: uw-menu-site-management
route_name: uw_cfg_common.analytics_ownership.form
weight: 0
uw_site_management.shortcuts:
title: 'Shortcuts'
menu_name: uw-menu-site-management
url: internal:/admin/config/user-interface/shortcut
weight: 0
uw_site_management.redirects:
title: 'Redirects'
menu_name: uw-menu-site-management
url: internal:/admin/config/search/redirect
weight: 0
uw_site_management.submit_request:
title: 'Submit request'
menu_name: uw-menu-site-management
url: mailto:rt-ist-wcms@rt.uwaterloo.ca
weight: 0
uw_site_management.wcms_how_to_documents:
title: 'WCMS how-to documents'
menu_name: uw-menu-site-management
......
......@@ -7,11 +7,15 @@
use Drupal\Component\Utility\Html;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\fillpdf\Controller\HandlePdfController;
use Drupal\fillpdf\Form\FillPdfFormForm;
use Drupal\media_library\MediaLibraryState;
use Drupal\user\UserInterface;
use Drupal\uw_cfg_common\Service\UWService;
......@@ -1112,3 +1116,172 @@ function uw_cfg_common_simplesamlphp_auth_user_attributes(UserInterface $account
// This implementation does not alter $account, so return is always FALSE.
return FALSE;
}
/**
* Return the most recent completed Webform submission for a user on a form.
*
* @param string $webform_id
* The entity ID of the Webform.
* @param int $uid
* The user ID of the user.
*
* @return int|null
* The submission ID or NULL if there are none.
*/
function uw_cfg_common_get_most_recent_webform_submission(string $webform_id, int $uid): ?int {
// Load submission IDs from webform_submission storage.
$webform_submission_storage = \Drupal::entityTypeManager()->getStorage('webform_submission');
$query = $webform_submission_storage->getQuery();
$query->condition('webform_id', $webform_id);
$query->condition('uid', $uid);
$query->condition('in_draft', 0);
$query->sort('created', 'ASC');
$entity_ids = $query->execute();
// If there is at least one, return the last as integer, otherwise NULL.
return $entity_ids ? (int) end($entity_ids) : NULL;
}
/**
* Implements hook_fillpdf_populate_pdf_context_alter().
*/
function uw_cfg_common_fillpdf_populate_pdf_context_alter(array &$context): void {
// If there are no webform_submission entities but there is at least one
// webform entity, add the most recent submission for each webform.
// Only do this for authenticated users.
$current_uid = (int) \Drupal::currentUser()->id();
if ($current_uid && empty($context['entity_ids']['webform_submission']) && !empty($context['entity_ids']['webform'])) {
foreach ($context['entity_ids']['webform'] as $webform_id) {
$entity_id = uw_cfg_common_get_most_recent_webform_submission($webform_id, $current_uid);
if ($entity_id) {
$context['entity_ids']['webform_submission'][$entity_id] = $entity_id;
}
}
}
}
/**
* Implements hook_ENTITY_TYPE_view().
*
* Provide download links to associated PDFs on Layout Builder pages containing
* a Webform block. Only the first such block is used.
*/
function uw_cfg_common_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void {
// Do nothing unless view_mode full.
if ($view_mode !== 'full') {
return;
}
// Do nothing unless user is authenticated.
$current_user = \Drupal::currentUser();
if (!$current_user->id()) {
return;
}
// Find the first Layout Builder block that contains a Webform.
$webform = NULL;
foreach (Element::children($build['_layout_builder']) as $child) {
foreach (Element::children($build['_layout_builder'][$child]) as $grand_child) {
foreach (Element::children($build['_layout_builder'][$child][$grand_child]) as $great_grand_child) {
$element = $build['_layout_builder'][$child][$grand_child][$great_grand_child];
if (isset($element['content']['#webform']) && $element['content']['#webform'] instanceof WebformInterface) {
$webform = $element['content']['#webform'];
break 3;
}
}
}
}
// Do nothing unless:
// Node is Webform.
// Webform "Show the notification about previous submissions" is enabled.
if (!$webform || !$webform->getSetting('form_previous_submissions')) {
return;
}
// Do nothing if fillpdf_form entity type does not exist.
$fillpdf_form_exists = \Drupal::entityTypeManager()->hasDefinition('fillpdf_form');
if (!$fillpdf_form_exists) {
return;
}
// Load the FillPDF form for this Webform.
$fillpdf_form_storage = \Drupal::entityTypeManager()->getStorage('fillpdf_form');
$query = $fillpdf_form_storage->getQuery();
$query->condition('default_entity_type', 'webform');
$query->condition('default_entity_id', $webform->id());
$fillpdf_forms = $query->execute();
$fillpdf_forms = $fillpdf_form_storage->loadMultiple($fillpdf_forms);
// Do nothing unless there are PDFs associated with this Webform.
if (!$fillpdf_forms) {
return;
}
// Do nothing unless there is a Webform submission by this user.
// Find the most recent submission to this Webform by the current user.
$webform_submission_entity_id = uw_cfg_common_get_most_recent_webform_submission($webform->id(), $current_user->id());
if (!$webform_submission_entity_id) {
return;
}
// For each FillPDF form, check access and generate a link with filename.
$pdf_links = [];
$fillpdf_link_manipulator = \Drupal::service('fillpdf.link_manipulator');
$fillpdf_access_helper = \Drupal::service('fillpdf.access_helper');
$handle_pdf_controller = HandlePdfController::create(\Drupal::getContainer());
foreach ($fillpdf_forms as $fid => $fillpdf_form) {
$parameters = ['fid' => $fid];
$pdf_link = $fillpdf_link_manipulator->generateLink($parameters);
$context = $fillpdf_link_manipulator->parseLink($pdf_link);
$has_generate_pdf_access = $fillpdf_access_helper->canGeneratePdfFromContext($context, $current_user);
if ($has_generate_pdf_access) {
$handle_pdf_controller->alterContext($context);
$filename = $handle_pdf_controller->getFilename($context);
$pdf_links[] = Link::fromTextAndUrl($filename, $pdf_link);
}
}
// Do nothing if no links to display.
if (!$pdf_links) {
return;
}
// Create status message.
$message = [
'#theme' => 'item_list',
'#items' => $pdf_links,
'#prefix' => t('Download PDF version of your form:'),
];
$message = \Drupal::service('renderer')->render($message);
\Drupal::messenger()->addStatus($message);
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Configure admin/structure/fillpdf/FID.
*/
function uw_cfg_common_form_fillpdf_form_edit_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
// We only use FillPDF with Webform, so hide the entity type selector and
// change the title of the entity selector.
$form['default_entity_type']['#access'] = FALSE;
$form['default_entity_id']['#title'] = t('Default Webform');
}
/**
* Implements hook_fillpdf_form_form_pre_form_build_alter().
*/
function uw_cfg_common_fillpdf_form_form_pre_form_build_alter(FillPdfFormForm $fillpdf_form_form): void {
// We only use FillPDF with Webform, so set the default entity type for any
// FillPDF form that does not have one to 'webform'.
$fillpdf_form = $fillpdf_form_form->getEntity();
$default_entity_type = $fillpdf_form->getDefaultEntityType();
if (!$default_entity_type) {
$fillpdf_form->set('default_entity_type', 'webform')->save();
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment