3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 class CRM_Case_XMLProcessor_Process
extends CRM_Case_XMLProcessor
{
18 protected $defaultAssigneeOptionsValues = [];
23 * @param string $caseType
24 * @param array $params
26 * @throws CRM_Core_Exception
28 public function run($caseType, &$params) {
29 $xml = $this->retrieve($caseType);
32 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
33 throw new CRM_Core_Exception(ts("Configuration file could not be retrieved for case type = '%1' %2.",
34 [1 => $caseType, 2 => $docLink]
38 $xmlProcessorProcess = new CRM_Case_XMLProcessor_Process();
39 $this->_isMultiClient
= $xmlProcessorProcess->getAllowMultipleCaseClients();
41 $this->process($xml, $params);
47 * @param bool $isLabel
48 * @param bool $maskAction
50 * @return array|bool|mixed
53 public function get($caseType, $fieldSet, $isLabel = FALSE, $maskAction = FALSE) {
54 $xml = $this->retrieve($caseType);
56 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
57 throw new CRM_Core_Exception(ts("Unable to load configuration file for the referenced case type: '%1' %2.",
58 [1 => $caseType, 2 => $docLink]
64 return $this->caseRoles($xml->CaseRoles
);
67 return $this->activitySets($xml->ActivitySets
);
70 return $this->activityTypes($xml->ActivityTypes
, FALSE, $isLabel, $maskAction);
76 * @param array $params
80 public function process($xml, &$params) {
81 $standardTimeline = $params['standardTimeline'] ??
NULL;
82 $activitySetName = $params['activitySetName'] ??
NULL;
84 if ('Open Case' == CRM_Utils_Array
::value('activityTypeName', $params)) {
85 // create relationships for the ones that are required
86 foreach ($xml->CaseRoles
as $caseRoleXML) {
87 foreach ($caseRoleXML->RelationshipType
as $relationshipTypeXML) {
88 // simplexml treats node values differently than you'd expect,
90 // Just using `if ($relationshipTypeXML->creator)` ends up always
91 // being true, so you have to cast to int or somehow force evaluation
92 // of the actual value. And casting to (bool) seems to behave
93 // differently on these objects than casting to (int).
94 if (!empty($relationshipTypeXML->creator
)) {
95 if (!$this->createRelationships($relationshipTypeXML,
99 throw new CRM_Core_Exception('Unable to create case relationships');
106 if ('Change Case Start Date' == CRM_Utils_Array
::value('activityTypeName', $params)) {
107 // delete all existing activities which are non-empty
108 $this->deleteEmptyActivity($params);
111 foreach ($xml->ActivitySets
as $activitySetsXML) {
112 foreach ($activitySetsXML->ActivitySet
as $activitySetXML) {
113 if ($standardTimeline) {
114 if (!empty($activitySetXML->timeline
)) {
115 return $this->processStandardTimeline($activitySetXML, $params);
118 elseif ($activitySetName) {
119 $name = (string) $activitySetXML->name
;
120 if ($name == $activitySetName) {
121 return $this->processActivitySet($activitySetXML, $params);
129 * @param $activitySetXML
130 * @param array $params
132 public function processStandardTimeline($activitySetXML, &$params) {
133 if ('Change Case Type' == CRM_Utils_Array
::value('activityTypeName', $params)
134 && CRM_Utils_Array
::value('resetTimeline', $params, TRUE)
136 // delete all existing activities which are non-empty
137 $this->deleteEmptyActivity($params);
140 foreach ($activitySetXML->ActivityTypes
as $activityTypesXML) {
141 foreach ($activityTypesXML as $activityTypeXML) {
142 $this->createActivity($activityTypeXML, $params);
148 * @param $activitySetXML
149 * @param array $params
151 public function processActivitySet($activitySetXML, &$params) {
152 foreach ($activitySetXML->ActivityTypes
as $activityTypesXML) {
153 foreach ($activityTypesXML as $activityTypeXML) {
154 $this->createActivity($activityTypeXML, $params);
160 * @param $caseRolesXML
161 * @param bool $isCaseManager
163 * @return array|mixed
165 public function &caseRoles($caseRolesXML, $isCaseManager = FALSE) {
166 // Look up relationship types according to the XML convention (described
167 // from perspective of non-client) but return the labels according to the UI
168 // convention (described from perspective of client)
169 $relationshipTypesToReturn = &$this->allRelationshipTypes(FALSE);
172 foreach ($caseRolesXML as $caseRoleXML) {
173 foreach ($caseRoleXML->RelationshipType
as $relationshipTypeXML) {
174 list($relationshipTypeID,) = $this->locateNameOrLabel($relationshipTypeXML);
175 if ($relationshipTypeID === FALSE) {
179 if (!$isCaseManager) {
180 $result[$relationshipTypeID] = $relationshipTypesToReturn[$relationshipTypeID];
182 elseif ($relationshipTypeXML->manager
== 1) {
183 return $relationshipTypeID;
191 * @param SimpleXMLElement $relationshipTypeXML
192 * @param array $params
195 * @throws CRM_Core_Exception
197 public function createRelationships($relationshipTypeXML, &$params) {
199 // get the relationship
200 list($relationshipType, $relationshipTypeName) = $this->locateNameOrLabel($relationshipTypeXML);
201 if ($relationshipType === FALSE) {
202 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
203 throw new CRM_Core_Exception(ts('Relationship type %1, found in case configuration file, is not present in the database %2',
204 [1 => $relationshipTypeName, 2 => $docLink]
208 $client = $params['clientID'];
209 if (!is_array($client)) {
213 foreach ($client as $key => $clientId) {
214 $relationshipParams = [
215 'relationship_type_id' => substr($relationshipType, 0, -4),
217 'case_id' => $params['caseID'],
218 'start_date' => date("Ymd"),
219 'end_date' => $params['relationship_end_date'] ??
NULL,
222 if (substr($relationshipType, -4) == '_b_a') {
223 $relationshipParams['contact_id_b'] = $clientId;
224 $relationshipParams['contact_id_a'] = $params['creatorID'];
226 if (substr($relationshipType, -4) == '_a_b') {
227 $relationshipParams['contact_id_a'] = $clientId;
228 $relationshipParams['contact_id_b'] = $params['creatorID'];
231 if (!$this->createRelationship($relationshipParams)) {
232 throw new CRM_Core_Exception('Unable to create case relationship');
239 * @param array $params
243 public function createRelationship(&$params) {
244 $dao = new CRM_Contact_DAO_Relationship();
245 $dao->copyValues($params);
246 // only create a relationship if it does not exist
247 if (!$dao->find(TRUE)) {
254 * @param $activityTypesXML
255 * @param bool $maxInst
256 * @param bool $isLabel
257 * @param bool $maskAction
261 public function activityTypes($activityTypesXML, $maxInst = FALSE, $isLabel = FALSE, $maskAction = FALSE) {
262 $activityTypes = CRM_Case_PseudoConstant
::caseActivityType(TRUE, TRUE);
264 foreach ($activityTypesXML as $activityTypeXML) {
265 foreach ($activityTypeXML as $recordXML) {
266 $activityTypeName = (string) $recordXML->name
;
267 $maxInstances = (string) $recordXML->max_instances
;
268 $activityTypeInfo = $activityTypes[$activityTypeName] ??
NULL;
270 if ($activityTypeInfo['id']) {
272 if ($maskAction == 'edit' && '0' === (string) $recordXML->editable
) {
273 $result[$maskAction][] = $activityTypeInfo['id'];
278 //if we want,labels of activities should be returned.
280 $result[$activityTypeInfo['id']] = $activityTypeInfo['label'];
283 $result[$activityTypeInfo['id']] = $activityTypeName;
288 $result[$activityTypeName] = $maxInstances;
296 // call option value hook
297 CRM_Utils_Hook
::optionValues($result, 'case_activity_type');
303 * @param SimpleXMLElement $caseTypeXML
305 * @return array<string> symbolic activity-type names
307 public function getDeclaredActivityTypes($caseTypeXML) {
310 if (!empty($caseTypeXML->ActivityTypes
) && $caseTypeXML->ActivityTypes
->ActivityType
) {
311 foreach ($caseTypeXML->ActivityTypes
->ActivityType
as $activityTypeXML) {
312 $result[] = (string) $activityTypeXML->name
;
316 if (!empty($caseTypeXML->ActivitySets
) && $caseTypeXML->ActivitySets
->ActivitySet
) {
317 foreach ($caseTypeXML->ActivitySets
->ActivitySet
as $activitySetXML) {
318 if ($activitySetXML->ActivityTypes
&& $activitySetXML->ActivityTypes
->ActivityType
) {
319 foreach ($activitySetXML->ActivityTypes
->ActivityType
as $activityTypeXML) {
320 $result[] = (string) $activityTypeXML->name
;
326 $result = array_unique($result);
332 * Relationships are straight from XML, described from perspective of non-client
334 * @param SimpleXMLElement $caseTypeXML
336 * @return array<string> symbolic relationship-type names
338 public function getDeclaredRelationshipTypes($caseTypeXML) {
341 if (!empty($caseTypeXML->CaseRoles
) && $caseTypeXML->CaseRoles
->RelationshipType
) {
342 foreach ($caseTypeXML->CaseRoles
->RelationshipType
as $relTypeXML) {
343 list(, $relationshipTypeMachineName) = $this->locateNameOrLabel($relTypeXML);
344 $result[] = $relationshipTypeMachineName;
348 $result = array_unique($result);
354 * @param array $params
356 public function deleteEmptyActivity(&$params) {
357 $activityContacts = CRM_Activity_BAO_ActivityContact
::buildOptions('record_type_id', 'validate');
358 $targetID = CRM_Utils_Array
::key('Activity Targets', $activityContacts);
362 FROM civicrm_activity a
363 INNER JOIN civicrm_activity_contact t ON t.activity_id = a.id
364 INNER JOIN civicrm_case_activity ca on ca.activity_id = a.id
365 WHERE t.contact_id = %1
366 AND t.record_type_id = $targetID
368 AND a.is_current_revision = 1
371 $sqlParams = [1 => [$params['clientID'], 'Integer'], 2 => [$params['caseID'], 'Integer']];
372 CRM_Core_DAO
::executeQuery($query, $sqlParams);
376 * @param array $params
380 public function isActivityPresent(&$params) {
383 FROM civicrm_activity a
384 INNER JOIN civicrm_case_activity ca on ca.activity_id = a.id
385 WHERE a.activity_type_id = %1
391 1 => [$params['activityTypeID'], 'Integer'],
392 2 => [$params['caseID'], 'Integer'],
394 $count = CRM_Core_DAO
::singleValueQuery($query, $sqlParams);
396 // check for max instance
397 $caseType = CRM_Case_BAO_Case
::getCaseType($params['caseID'], 'name');
398 $maxInstance = self
::getMaxInstance($caseType, $params['activityTypeName']);
400 return $maxInstance ?
($count < $maxInstance ?
FALSE : TRUE) : FALSE;
404 * @param $activityTypeXML
405 * @param array $params
408 * @throws CRM_Core_Exception
411 public function createActivity($activityTypeXML, &$params) {
412 $activityTypeName = (string) $activityTypeXML->name
;
413 $activityTypes = CRM_Case_PseudoConstant
::caseActivityType(TRUE, TRUE);
414 $activityTypeInfo = $activityTypes[$activityTypeName] ??
NULL;
416 if (!$activityTypeInfo) {
417 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
418 throw new CRM_Core_Exception(ts('Activity type %1, found in case configuration file, is not present in the database %2',
419 [1 => $activityTypeName, 2 => $docLink]
423 $activityTypeID = $activityTypeInfo['id'];
425 if (isset($activityTypeXML->status
)) {
426 $statusName = (string) $activityTypeXML->status
;
429 $statusName = 'Scheduled';
432 $client = (array) $params['clientID'];
436 if (isset($activityTypeXML->order
)) {
437 $orderVal = (string) $activityTypeXML->order
;
440 if ($activityTypeName == 'Open Case') {
442 'activity_type_id' => $activityTypeID,
443 'source_contact_id' => $params['creatorID'],
445 'is_current_revision' => 1,
446 'subject' => !empty($params['subject']) ?
$params['subject'] : $activityTypeName,
447 'status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Activity_BAO_Activity', 'activity_status_id', $statusName),
448 'target_contact_id' => $client,
449 'medium_id' => $params['medium_id'] ??
NULL,
450 'location' => $params['location'] ??
NULL,
451 'details' => $params['details'] ??
NULL,
452 'duration' => $params['duration'] ??
NULL,
453 'weight' => $orderVal,
458 'activity_type_id' => $activityTypeID,
459 'source_contact_id' => $params['creatorID'],
461 'is_current_revision' => 1,
462 'status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Activity_BAO_Activity', 'activity_status_id', $statusName),
463 'target_contact_id' => $client,
464 'weight' => $orderVal,
468 $activityParams['assignee_contact_id'] = $this->getDefaultAssigneeForActivity($activityParams, $activityTypeXML, $params['caseID']);
470 //parsing date to default preference format
471 $params['activity_date_time'] = CRM_Utils_Date
::processDate($params['activity_date_time']);
473 if ($activityTypeName == 'Open Case') {
474 // we don't set activity_date_time for auto generated
475 // activities, but we want it to be set for open case.
476 $activityParams['activity_date_time'] = $params['activity_date_time'];
477 if (array_key_exists('custom', $params) && is_array($params['custom'])) {
478 $activityParams['custom'] = $params['custom'];
481 // Add parameters for attachments
483 $numAttachments = Civi
::settings()->get('max_attachments');
484 for ($i = 1; $i <= $numAttachments; $i++
) {
485 $attachName = "attachFile_$i";
486 if (isset($params[$attachName]) && !empty($params[$attachName])) {
487 $activityParams[$attachName] = $params[$attachName];
492 $activityDate = NULL;
493 //get date of reference activity if set.
494 if ($referenceActivityName = (string) $activityTypeXML->reference_activity
) {
496 //we skip open case as reference activity.CRM-4374.
497 if (!empty($params['resetTimeline']) && $referenceActivityName == 'Open Case') {
498 $activityDate = $params['activity_date_time'];
501 $referenceActivityInfo = $activityTypes[$referenceActivityName] ??
NULL;
502 if ($referenceActivityInfo['id']) {
503 $caseActivityParams = ['activity_type_id' => $referenceActivityInfo['id']];
505 //if reference_select is set take according activity.
506 if ($referenceSelect = (string) $activityTypeXML->reference_select
) {
507 $caseActivityParams[$referenceSelect] = 1;
510 $referenceActivity = CRM_Case_BAO_Case
::getCaseActivityDates($params['caseID'], $caseActivityParams, TRUE);
512 if (is_array($referenceActivity)) {
513 foreach ($referenceActivity as $aId => $details) {
514 $activityDate = $details['activity_date'] ??
NULL;
521 if (!$activityDate) {
522 $activityDate = $params['activity_date_time'];
524 list($activity_date, $activity_time) = CRM_Utils_Date
::setDateDefaults($activityDate);
525 $activityDateTime = CRM_Utils_Date
::processDate($activity_date, $activity_time);
526 //add reference offset to date.
527 if ((int) $activityTypeXML->reference_offset
) {
528 $activityDateTime = CRM_Utils_Date
::intervalAdd('day', (int) $activityTypeXML->reference_offset
,
533 $activityParams['activity_date_time'] = CRM_Utils_Date
::format($activityDateTime);
536 // if same activity is already there, skip and dont touch
537 $params['activityTypeID'] = $activityTypeID;
538 $params['activityTypeName'] = $activityTypeName;
539 if ($this->isActivityPresent($params)) {
542 $activityParams['case_id'] = $params['caseID'];
543 if (!empty($activityParams['is_auto'])) {
544 $activityParams['skipRecentView'] = TRUE;
547 // @todo - switch to using api & remove the parameter pre-wrangling above.
548 $activity = CRM_Activity_BAO_Activity
::create($activityParams);
551 throw new CRM_Core_Exception('Unable to create Activity');
554 // create case activity record
556 'activity_id' => $activity->id
,
557 'case_id' => $params['caseID'],
559 CRM_Case_BAO_Case
::processCaseActivity($caseParams);
564 * Return the default assignee contact for the activity.
566 * @param array $activityParams
567 * @param object $activityTypeXML
570 * @return int|null the ID of the default assignee contact or null if none.
572 protected function getDefaultAssigneeForActivity($activityParams, $activityTypeXML, $caseId) {
573 if (!isset($activityTypeXML->default_assignee_type
)) {
577 $defaultAssigneeOptionsValues = $this->getDefaultAssigneeOptionValues();
579 switch ($activityTypeXML->default_assignee_type
) {
580 case $defaultAssigneeOptionsValues['BY_RELATIONSHIP']:
581 return $this->getDefaultAssigneeByRelationship($activityParams, $activityTypeXML, $caseId);
584 case $defaultAssigneeOptionsValues['SPECIFIC_CONTACT']:
585 return $this->getDefaultAssigneeBySpecificContact($activityTypeXML);
588 case $defaultAssigneeOptionsValues['USER_CREATING_THE_CASE']:
589 return $activityParams['source_contact_id'];
592 case $defaultAssigneeOptionsValues['NONE']:
599 * Fetches and caches the activity's default assignee options.
603 protected function getDefaultAssigneeOptionValues() {
604 if (!empty($this->defaultAssigneeOptionsValues
)) {
605 return $this->defaultAssigneeOptionsValues
;
608 $defaultAssigneeOptions = civicrm_api3('OptionValue', 'get', [
609 'option_group_id' => 'activity_default_assignee',
610 'options' => ['limit' => 0],
613 foreach ($defaultAssigneeOptions['values'] as $option) {
614 $this->defaultAssigneeOptionsValues
[$option['name']] = $option['value'];
617 return $this->defaultAssigneeOptionsValues
;
621 * Returns the default assignee for the activity by searching for the target's
622 * contact relationship type defined in the activity's details.
624 * @param array $activityParams
625 * @param object $activityTypeXML
628 * @return int|null the ID of the default assignee contact or null if none.
630 protected function getDefaultAssigneeByRelationship($activityParams, $activityTypeXML, $caseId) {
631 $isDefaultRelationshipDefined = isset($activityTypeXML->default_assignee_relationship
)
632 && preg_match('/\d+_[ab]_[ab]/', $activityTypeXML->default_assignee_relationship
);
634 if (!$isDefaultRelationshipDefined) {
638 $targetContactId = is_array($activityParams['target_contact_id'])
639 ? CRM_Utils_Array
::first($activityParams['target_contact_id'])
640 : $activityParams['target_contact_id'];
641 list($relTypeId, $a, $b) = explode('_', $activityTypeXML->default_assignee_relationship
);
644 'relationship_type_id' => $relTypeId,
645 "contact_id_$b" => $targetContactId,
647 'case_id' => $caseId,
648 'options' => ['limit' => 1],
651 if ($this->isBidirectionalRelationshipType($relTypeId)) {
652 $params["contact_id_$a"] = $targetContactId;
653 $params['options']['or'] = [['contact_id_a', 'contact_id_b']];
656 $relationships = civicrm_api3('Relationship', 'get', $params);
657 if (empty($relationships['count'])) {
658 $params['case_id'] = ['IS NULL' => 1];
659 $relationships = civicrm_api3('Relationship', 'get', $params);
662 if ($relationships['count']) {
663 $relationship = CRM_Utils_Array
::first($relationships['values']);
665 // returns the contact id on the other side of the relationship:
666 return (int) $relationship['contact_id_a'] === (int) $targetContactId
667 ?
$relationship['contact_id_b']
668 : $relationship['contact_id_a'];
676 * Determines if the given relationship type is bidirectional or not by
677 * comparing their labels.
681 protected function isBidirectionalRelationshipType($relationshipTypeId) {
682 $relationshipTypeResult = civicrm_api3('RelationshipType', 'get', [
683 'id' => $relationshipTypeId,
684 'options' => ['limit' => 1],
687 if ($relationshipTypeResult['count'] === 0) {
691 $relationshipType = CRM_Utils_Array
::first($relationshipTypeResult['values']);
693 return $relationshipType['label_b_a'] === $relationshipType['label_a_b'];
697 * Returns the activity's default assignee for a specific contact if the contact exists,
698 * otherwise returns null.
700 * @param object $activityTypeXML
704 protected function getDefaultAssigneeBySpecificContact($activityTypeXML) {
705 if (!$activityTypeXML->default_assignee_contact
) {
709 $contact = civicrm_api3('Contact', 'get', [
710 'id' => $activityTypeXML->default_assignee_contact
,
713 if ($contact['count'] == 1) {
714 return $activityTypeXML->default_assignee_contact
;
721 * @param $activitySetsXML
725 public static function activitySets($activitySetsXML) {
727 foreach ($activitySetsXML as $activitySetXML) {
728 foreach ($activitySetXML as $recordXML) {
729 $activitySetName = (string) $recordXML->name
;
730 $activitySetLabel = (string) $recordXML->label
;
731 $result[$activitySetName] = $activitySetLabel;
740 * @param string|null $activityTypeName
742 * @return array|bool|mixed
743 * @throws CRM_Core_Exception
745 public function getMaxInstance($caseType, $activityTypeName = NULL) {
746 $xml = $this->retrieve($caseType);
748 if ($xml === FALSE) {
749 throw new CRM_Core_Exception('Unable to locate xml definition for case type ' . $caseType);
752 $activityInstances = $this->activityTypes($xml->ActivityTypes
, TRUE);
753 return $activityTypeName ? CRM_Utils_Array
::value($activityTypeName, $activityInstances) : $activityInstances;
759 * @return array|mixed
761 public function getCaseManagerRoleId($caseType) {
762 $xml = $this->retrieve($caseType);
763 return $this->caseRoles($xml->CaseRoles
, TRUE);
767 * @param string $caseType
769 * @return array<\Civi\CCase\CaseChangeListener>
771 public function getListeners($caseType) {
772 $xml = $this->retrieve($caseType);
774 if ($xml->Listeners
&& $xml->Listeners
->Listener
) {
775 foreach ($xml->Listeners
->Listener
as $listenerXML) {
776 $class = (string) $listenerXML;
777 $listeners[] = new $class();
786 public function getRedactActivityEmail() {
787 return $this->getBoolSetting('civicaseRedactActivityEmail', 'RedactActivityEmail');
791 * Retrieves AllowMultipleCaseClients setting.
794 * 1 if allowed, 0 if not
796 public function getAllowMultipleCaseClients() {
797 return $this->getBoolSetting('civicaseAllowMultipleClients', 'AllowMultipleCaseClients');
801 * Retrieves NaturalActivityTypeSort setting.
804 * 1 if natural, 0 if alphabetic
806 public function getNaturalActivityTypeSort() {
807 return $this->getBoolSetting('civicaseNaturalActivityTypeSort', 'NaturalActivityTypeSort');
811 * @param string $settingKey
812 * @param string $xmlTag
813 * @param mixed $default
817 private function getBoolSetting($settingKey, $xmlTag, $default = 0) {
818 $setting = Civi
::settings()->get($settingKey);
819 if ($setting !== 'default') {
820 return (int) $setting;
822 if ($xml = $this->retrieve("Settings")) {
823 return (string) $xml->{$xmlTag} ?
1 : 0;
829 * At some point name and label got mixed up for case roles.
830 * Check against known machine name values, and then if no match check
832 * This is subject to some edge cases, but we catch those with a system
834 * We do this to avoid requiring people to update their xml files which can
835 * be stored in external files we can't/don't want to edit.
837 * @param SimpleXMLElement $xml
839 * @return array[bool|string,string]
841 public function locateNameOrLabel($xml) {
842 $lookupString = (string) $xml->name
;
844 // Don't use pseudoconstant because we need everything both name and
845 // label and disabled types.
846 $relationshipTypes = civicrm_api3('RelationshipType', 'get', [
847 'options' => ['limit' => 0],
850 // First look and see if it matches a machine name in the system.
851 // There are some edge cases here where we've actually been passed in a
852 // display label and it happens to match the machine name for a different
853 // db entry, but we have a system status check.
854 // But, we do want to check against the a_b version first, because of the
855 // way direction matters and that for bidirectional only one is present in
856 // the list where this eventually gets used, so return that first.
857 $relationshipTypeMachineNames = array_column($relationshipTypes, 'id', 'name_a_b');
858 if (isset($relationshipTypeMachineNames[$lookupString])) {
859 return ["{$relationshipTypeMachineNames[$lookupString]}_b_a", $lookupString];
861 $relationshipTypeMachineNames = array_column($relationshipTypes, 'id', 'name_b_a');
862 if (isset($relationshipTypeMachineNames[$lookupString])) {
863 return ["{$relationshipTypeMachineNames[$lookupString]}_a_b", $lookupString];
866 // Now at this point assume we've been passed a display label, so find
867 // what it matches and return the associated machine name. This is a bit
868 // trickier because suppose somebody has changed the display labels so
869 // that they are now the same, but the machine names are different. We
870 // don't know which to return and so while it's the right relationship type
871 // it might be the backwards direction. We have to pick one to try first.
873 $relationshipTypeDisplayLabels = array_column($relationshipTypes, 'id', 'label_a_b');
874 if (isset($relationshipTypeDisplayLabels[$lookupString])) {
876 "{$relationshipTypeDisplayLabels[$lookupString]}_b_a",
877 $relationshipTypes[$relationshipTypeDisplayLabels[$lookupString]]['name_a_b'],
880 $relationshipTypeDisplayLabels = array_column($relationshipTypes, 'id', 'label_b_a');
881 if (isset($relationshipTypeDisplayLabels[$lookupString])) {
883 "{$relationshipTypeDisplayLabels[$lookupString]}_a_b",
884 $relationshipTypes[$relationshipTypeDisplayLabels[$lookupString]]['name_b_a'],
888 // Just go with what we were passed in, even though it doesn't seem
889 // to match *anything*. This was what it did before.
890 return [FALSE, $lookupString];