Commit dfa047da authored by Chris Shantz's avatar Chris Shantz
Browse files

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

parents 53d6cfa4 862c9911
......@@ -33,6 +33,12 @@ content:
size: 60
placeholder: ''
third_party_settings: { }
publish_on:
type: datetime_timestamp_no_default
weight: 30
region: content
settings: { }
third_party_settings: { }
status:
type: boolean_checkbox
settings:
......@@ -45,5 +51,11 @@ content:
settings: { }
third_party_settings: { }
region: content
unpublish_on:
type: datetime_timestamp_no_default
weight: 30
region: content
settings: { }
third_party_settings: { }
hidden:
path: true
langcode: en
status: true
dependencies: { }
id: inline_blockuw_cbl_mailchimp
block_id: 'inline_block:uw_cbl_mailchimp'
category: uw_bc_content
label: Mailchimp
image_path: images/layout_builder_browser/mailchimp.svg
image_path_base: 'theme:uw_fdsu_theme_resp'
image_alt: ''
weight: null
langcode: en
status: true
dependencies: { }
id: inline_blockuw_cbl_social_intents
block_id: 'inline_block:uw_cbl_social_intents'
category: uw_bc_content
label: 'Social Intents'
image_path: images/layout_builder_browser/socialintents.svg
image_path_base: 'theme:uw_fdsu_theme_resp'
image_alt: ''
weight: null
langcode: en
status: true
dependencies: { }
id: uw_lbb_project_listing
block_id: 'views_block:uw_view_projects-projects_block'
category: uw_bc_listings
label: 'Project list'
weight: 0
image_path: images/layout_builder_browser/projectlist.svg
image_path_base: 'theme:uw_fdsu_theme_resp'
image_alt: 'Project list'
langcode: en
status: true
dependencies: { }
id: uw_lbb_project_search
block_id: uw_cbl_project_search
category: uw_bc_searches
label: 'Project search'
weight: 0
image_path: images/layout_builder_browser/projectsearch.svg
image_path_base: 'theme:uw_fdsu_theme_resp'
image_alt: 'Project search'
langcode: en
status: true
dependencies: { }
id: uw_lbb_project_teaser
block_id: uw_cbl_project_teaser
category: uw_bc_teasers
label: 'Project teaser'
weight: 0
image_path: images/layout_builder_browser/projectteaser.svg
image_path_base: 'theme:uw_fdsu_theme_resp'
image_alt: 'Project teaser'
......@@ -17,7 +17,7 @@ entity_type_groups:
advanced: advanced
open_graph: open_graph
twitter_cards: twitter_cards
schema_web_page: schema_person
schema_person: schema_person
uw_ct_event:
basic: basic
advanced: advanced
......@@ -41,13 +41,20 @@ entity_type_groups:
advanced: advanced
open_graph: open_graph
twitter_cards: twitter_cards
schema_web_page: schema_person
schema_person: schema_person
uw_ct_project:
basic: basic
advanced: advanced
open_graph: open_graph
twitter_cards: twitter_cards
schema_web_page: schema_web_page
uw_ct_service:
basic: basic
advanced: advanced
open_graph: open_graph
twitter_cards: twitter_cards
schema_web_page: schema_web_page
schema_service: schema_service
uw_ct_web_page:
basic: basic
advanced: advanced
......
......@@ -13,6 +13,7 @@ allowed_bundles:
- uw_ct_news_item
- uw_ct_opportunity
- uw_ct_profile
- uw_ct_project
- uw_ct_service
- uw_ct_sidebar
- uw_ct_web_page
services:
uw_cfg_common.commands:
class: Drupal\uw_cfg_common\Commands\UwDrushCommands
arguments: ['@entity_type.manager', '@uw_cfg_common.missing_blocks']
arguments: ['@entity_type.manager', '@uw_cfg_common.missing_blocks', '@config.factory', '@request_stack']
tags:
- { name: drush.command }
......@@ -2,6 +2,7 @@
namespace Drupal\uw_cfg_common\Commands;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\uw_cfg_common\Service\UWMissingBlocks;
use Drupal\uw_cfg_common\UwRoles\UwRoles;
......@@ -29,12 +30,20 @@ class UwDrushCommands extends DrushCommands {
*/
protected $missingBlocks;
/**
* Config factory from core.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* {@inheritDoc}
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager, UWMissingBlocks $missingBlocks) {
public function __construct(EntityTypeManagerInterface $entityTypeManager, UWMissingBlocks $missingBlocks, ConfigFactoryInterface $configFactory) {
$this->entityTypeManager = $entityTypeManager;
$this->missingBlocks = $missingBlocks;
$this->configFactory = $configFactory;
}
/**
......@@ -167,4 +176,47 @@ class UwDrushCommands extends DrushCommands {
$this->logger()->success('Missing blocks removed from saved and unsaved layouts.');
}
/**
* Command to retrieve scheduler's lightweight cron key.
*
* @return string
* Lightweight cron key.
*
* @command uw:lightweight-cron-key
* @aliases uw-lwc-key
* @usage drush uw-lwc-key
* - Return light weight cron key.
*/
public function getLightWeightCronKey(): string {
$key = '';
$config = $this->configFactory->get('scheduler.settings');
if (!empty($config)) {
$key = $config->get('lightweight_cron_access_key');
}
return $key;
}
/**
* Command to retrieve scheduler's lightweight cron path.
*
* @return string
* Lightweight cron path.
*
* @command uw:lightweight-cron-path
* @aliases uw-lwc-path
* @usage drush uw-lwc-path
* - Return light weight cron url with key.
*/
public function getLightWeightCronPath(): string {
$path = '';
if ($key = $this->getLightWeightCronKey()) {
$path = '/scheduler/cron/' . $key;
}
return $path;
}
}
......@@ -192,6 +192,7 @@ class UWService implements UWServiceInterface {
'uw_ct_news_item',
'uw_ct_opportunity',
'uw_ct_profile',
'uw_ct_project',
'uw_ct_web_page',
'uw_ct_service',
];
......@@ -205,6 +206,7 @@ class UWService implements UWServiceInterface {
'uw_ct_news_item',
'uw_ct_opportunity',
'uw_ct_profile',
'uw_ct_project',
'uw_ct_catalog_item',
'uw_ct_service',
];
......@@ -219,6 +221,7 @@ class UWService implements UWServiceInterface {
'uw_ct_news_item',
'uw_ct_opportunity',
'uw_ct_profile',
'uw_ct_project',
'uw_ct_web_page',
];
break;
......@@ -327,6 +330,7 @@ class UWService implements UWServiceInterface {
'uw_ct_news_item' => TRUE,
'uw_ct_opportunity' => FALSE,
'uw_ct_profile' => FALSE,
'uw_ct_project' => FALSE,
'uw_ct_service' => TRUE,
'uw_ct_sidebar' => FALSE,
'uw_ct_site_footer' => FALSE,
......
......@@ -81,6 +81,10 @@ class UwNodeContent {
$content_data = $this->getProfileContent($node_flags);
break;
case 'uw_ct_project':
$content_data = $this->getProjectContent($node_flags);
break;
case 'uw_ct_service':
$content_data = $this->getServiceContent($node_flags);
break;
......@@ -598,6 +602,7 @@ class UwNodeContent {
$content_data['footer']['links']['has_children'] = TRUE;
$content_data['footer']['links']['profile'] = $this->addToContentData('link', 'field_uw_ct_profile_info_link');
$content_data['footer']['links']['webpage'] = $this->addToContentData('link', 'field_uw_ct_profile_link_persona');
$content_data['footer']['links']['link_to_contact'] = $this->addToContentData('link', 'field_uw_ct_profile_link_contact');
}
// Get the tags, if any.
......@@ -613,6 +618,56 @@ class UwNodeContent {
return $content_data;
}
/**
* Get the node content for project content type.
*
* @param array $node_flags
* The flags for the node.
*
* @return array
* Array of content to get from the node.
*/
public function getProjectContent(array $node_flags): array {
// Get the content data.
$content_data = $this->setupContentData($node_flags);
// Setup the actual content.
if ($node_flags['get_content']) {
$content_data['content'] = $this->addToContentData('content', 'field_uw_project_summary');
}
// Get listing image.
if ($node_flags['get_image']) {
$content_data['image'] = $this->addToContentData('image', 'field_uw_project_listing_image');
$content_data['image']['extra_options'] = [
'type' => 'listing_image',
'is_responsive' => TRUE,
];
}
// Get the footer.
if ($node_flags['get_footer']) {
$content_data['footer']['project_details']['has_children'] = TRUE;
$content_data['footer']['project_details']['status'] = $this->addToContentData('terms', ['field_uw_project_status']);
$content_data['footer']['project_details']['topics'] = $this->addToContentData('terms', ['field_uw_project_topics']);
$content_data['footer']['project_members'] = $this->addToContentData('project_members', 'field_uw_project_members');
$content_data['footer']['timeline'] = $this->addToContentData('timeline', 'field_uw_project_timeline');
}
// Get the tags, if any.
if ($node_flags['get_tags']) {
$content_data['tags'] = $this->addToContentData(
'terms',
[
'field_uw_audience',
]
);
}
return $content_data;
}
/**
* Get the node content for service content type.
*
......
......@@ -149,8 +149,13 @@ class UwNodeData {
// If we are on the footer, clean it by itself,
// since it is 3D array.
// We need to add a continue here so that elements
// from the footer are not cleared out, if we do not
// have the continue, footers with one element will be
// set to null.
if ($index == 'footer') {
$node_data['footer'] = $this->cleanFooterNodeData($node_data['footer']);
continue;
}
// If the element is an array, step through all the
......
......@@ -165,6 +165,11 @@ class UwNodeFieldValue {
}
}
// Project members.
if ($type == 'project_members') {
return $this->getProjectMembers($node, $field_name);
}
// Source or hero image field type.
if ($type == 'sources' || $type == 'hero') {
return $this->getSources($node, $field_name);
......@@ -176,6 +181,11 @@ class UwNodeFieldValue {
return $this->getCatalogTags($node, $field_name);
}
// Timeline from smart date range.
if ($type == 'timeline') {
return $this->getTimeline($node, $field_name);
}
// Title of the node.
if ($type == 'title') {
return $node->getTitle();
......@@ -694,9 +704,6 @@ class UwNodeFieldValue {
// Get the date query parameter.
$date_parameter = $this->requestStack->getCurrentRequest()->query->get('date');
// Get the date type query parameter.
$date_type = $this->requestStack->getCurrentRequest()->query->get('date_type');
// If there is a date query parameter, convert
// to timestamp so we can compare against dates
// in the event. If there is no parameter, set
......@@ -714,9 +721,9 @@ class UwNodeFieldValue {
// ISTWCMS-5088: we need to ensure that at least
// some dates show on the node page, so let's just
// display them all or if operator is >=.
// display them all.
// If not node page, only get dates in the future.
if ($view_mode == 'full' || ($date_type !== '>=')) {
if ($view_mode == 'full') {
$return_dates[] = $this->getDate($date, 'event');
}
......@@ -731,6 +738,19 @@ class UwNodeFieldValue {
}
}
// If the dates are an array and there is more than one,
// sort the array so that the dates appear in order.
if (
is_array($return_dates) &&
count($return_dates) > 1
) {
// Sorting the array by the start date, so that
// the dates actually appear in the correct order.
$keys = array_column($return_dates, 'start_date');
array_multisort($keys, SORT_ASC, $return_dates);
}
return $return_dates;
}
......@@ -861,23 +881,25 @@ class UwNodeFieldValue {
if ($type == 'event') {
// If this is the same day, get the date and the start and end times.
if ($date['duration'] < '1439') {
$return_date['all_day'] = FALSE;
$return_date['date_range'] = TRUE;
$return_date['same_day'] = TRUE;
$return_date['start_date'] = $date['value'];
$return_date['end_date'] = $date['end_value'];
}
// This is not the day, get the start and end date with time.
elseif ($date['duration'] > '1439') {
$return_date['all_day'] = FALSE;
$return_date['date_range'] = TRUE;
$return_date['same_day'] = FALSE;
$return_date['start_date'] = $date['value'];
$return_date['end_date'] = $date['end_value'];
}
// The all date case, duration is always 1439.
else {
$return_date['all_day'] = TRUE;
$return_date['date'] = $date['value'];
$return_date['date_range'] = TRUE;
$return_date['same_day'] = FALSE;
}
$return_date['start_date'] = $date['value'];
$return_date['end_date'] = $date['end_value'];
}
else {
$return_date['date'] = $date[0];
......@@ -918,7 +940,29 @@ class UwNodeFieldValue {
else {
$link_info['uri'] = URL::fromUri($ld['uri'])->toString();
}
$link_info['title'] = $ld['title'];
// For 'Link to contact' field,
// if the uri is like 'internal:/blog', the link title is empty.
// if the uri is like 'entity:node/6', set the node title as link title.
if ($field_name == 'field_uw_ct_profile_link_contact') {
// Get uri from the given link data.
$uri = $ld['uri'];
// Split uri into an array.
$nid = explode('/', $uri);
// Get the node object.
$node = Node::load($nid[1]);
// If it is node object, set the link node title as link title.
if ($node) {
$link_info['title'] = $node->get('title')->value;
}
// If it is not node object, still use the existing title value.
else {
$link_info['title'] = $ld['title'];
}
}
// For other link fields except 'Link to contact' field.
else {
$link_info['title'] = $ld['title'];
}
$return_link_data[] = $link_info;
}
......@@ -927,4 +971,123 @@ class UwNodeFieldValue {
return $return_link_data;
}
/**
* Gets timeline from smart date range.
*
* @param \Drupal\node\Entity\Node $node
* Node entity.
* @param string $field_name
* The field name that has the timeline.
*
* @return array
* Array with link info.
*/
public function getTimeline(Node $node, string $field_name): array {
$timeline = $node->$field_name->getValue();
if ($timeline) {
$timeline = [
'start_date' => $timeline[0]['value'],
'end_date' => $timeline[0]['end_value'],
];
}
return $timeline;
}
/**
* Gets project members.
*
* @param \Drupal\node\Entity\Node $node
* Node entity.
* @param string $field_name
* The field name that has the timeline.
*
* @return array|null
* Array with link info.
*/
public function getProjectMembers(Node $node, string $field_name): ?array {
// Ensuring that we return something.
$project_members = NULL;
// Get the members from the node, which is a paragraph.
$members = $node->$field_name->referencedEntities();
// Step through each of the members and get the info.
foreach ($members as $member) {
// Default empty variables for roles and links.
$roles = NULL;
$link = NULL;
$member_name = NULL;
// Get the tids for the role from the paragraph.
$role_tids = $member->field_uw_project_role->getValue();
// If there are role tids, process them.
if ($role_tids) {
// Step through each of the tids and get the name of the role term.
foreach ($role_tids as $role_tid) {
// Load the term.
$role = $this->entityTypeManager->getStorage('taxonomy_term')->load($role_tid['target_id']);
// Set the role name in the array.
$roles[] = [
'title' => $role->getName(),
'url' => $role->toUrl()->toString(),
];
}
}
// Get the link from the paragraph.
$link_data = $member->field_uw_project_members_link->getValue();
// If there is data in the link, get the variables.
if ($link_data) {
// Step through each link and get the info.
foreach ($link_data as $ld) {
// Get correct uri, if external just use uri from node
// value, if not, then generate url from uri.
if (UrlHelper::isExternal($ld['uri'])) {
$link = $ld['uri'];
}
else {
$link = URL::fromUri($ld['uri'])->toString();
}
}
}
// Setup member name, if there is no member use the link.
if (
$member->field_uw_project_name->value == NULL &&
$link !== NULL
) {
$member_name = $link;
}
else {
$member_name = $member->field_uw_project_name->value;
}
// If there is any values in the project members,
// add it to the variables.
if ($member_name || $link || $roles) {
// Setup the project members array.
$project_members[] = [
'name' => $member_name,
'roles' => $roles,
'link' => $link,
];
}
}
return $project_members;
}
}
......@@ -207,6 +207,34 @@ class UwPermissions {
),
],
// Project permissions.
'Project' => [
'Use content type' =>
UwPermissions::buildRolePermissionsListContentType(
'uw_ct_project'
),
'Create/edit roles' =>
UwPermissions::buildRolePermissionsListTaxonomyTerm(
'uw_vocab_project_roles',
['create', 'edit']
),
'Delete roles' =>
UwPermissions::buildRolePermissionsListTaxonomyTerm(
'uw_vocab_project_roles',
['delete']
),
'Create/edit topics' =>
UwPermissions::buildRolePermissionsListTaxonomyTerm(
'uw_vocab_project_topics',
['create', 'edit']
),
'Delete topics' =>
UwPermissions::buildRolePermissionsListTaxonomyTerm(
'uw_vocab_project_topics',
['delete']
),