From fba49a5a0432dc5f5976eada16974207eb07aeb4 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Sat, 1 Oct 2022 13:52:43 +0200 Subject: [PATCH] chg: [internal] Simplify ObjectTemplate::checkTemplateConformityBasedOnTypes method --- app/Controller/ObjectsController.php | 22 ++----- app/Model/MispObject.php | 43 +------------ app/Model/ObjectTemplate.php | 93 +++++++++++++++++++++------- 3 files changed, 78 insertions(+), 80 deletions(-) diff --git a/app/Controller/ObjectsController.php b/app/Controller/ObjectsController.php index 2a5677a6b..9257620ed 100644 --- a/app/Controller/ObjectsController.php +++ b/app/Controller/ObjectsController.php @@ -1141,23 +1141,8 @@ class ObjectsController extends AppController $selectedAttributes = $this->_jsonDecode($selectedAttributes); $res = $this->MispObject->validObjectsFromAttributeTypes($this->Auth->user(), $eventId, $selectedAttributes); - $potentialTemplates = $res['templates']; - $attributeTypes = $res['types']; - usort($potentialTemplates, function($a, $b) { - if ($a['ObjectTemplate']['id'] == $b['ObjectTemplate']['id']) { - return 0; - } else if (is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) { - return count($a['ObjectTemplate']['compatibility']) > count($b['ObjectTemplate']['compatibility']) ? 1 : -1; - } else if (is_array($a['ObjectTemplate']['compatibility']) && !is_array($b['ObjectTemplate']['compatibility'])) { - return 1; - } else if (!is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) { - return -1; - } else { // sort based on invalidTypes count - return count($a['ObjectTemplate']['invalidTypes']) > count($b['ObjectTemplate']['invalidTypes']) ? 1 : -1; - } - }); - $this->set('potential_templates', $potentialTemplates); - $this->set('selected_types', $attributeTypes); + $this->set('potential_templates', $res['templates']); + $this->set('selected_types', $res['types']); $this->set('event_id', $eventId); } @@ -1234,7 +1219,8 @@ class ObjectsController extends AppController if (empty($template)) { throw new NotFoundException(__('Invalid template.')); } - $conformity_result = $this->MispObject->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $selected_attributes); + $attributeTypes = array_column(array_column($selected_attributes, 'Attribute'), 'type'); + $conformity_result = $this->MispObject->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $attributeTypes); $skipped_attributes = 0; foreach ($selected_attributes as $i => $attribute) { if (in_array($attribute['Attribute']['type'], $conformity_result['invalidTypes'], true)) { diff --git a/app/Model/MispObject.php b/app/Model/MispObject.php index 8a27d24e8..8ecf7fb31 100644 --- a/app/Model/MispObject.php +++ b/app/Model/MispObject.php @@ -1235,51 +1235,14 @@ class MispObject extends AppModel 'Attribute.event_id' => $eventId, 'Attribute.object_id' => 0, ], + 'fields' => ['Attribute.type'], ]); if (empty($attributes)) { return array('templates' => array(), 'types' => array()); } - $attributeTypes = array(); - foreach ($attributes as $i => $attribute) { - $attributeTypes[$attribute['Attribute']['type']] = true; - $attributes[$i]['Attribute']['object_relation'] = $attribute['Attribute']['type']; - } - $attributeTypes = array_keys($attributeTypes); - $potentialTemplateIds = $this->ObjectTemplate->find('column', array( - 'recursive' => -1, - 'fields' => array( - 'ObjectTemplate.id', - ), - 'conditions' => array( - 'ObjectTemplate.active' => true, - 'ObjectTemplateElement.type' => $attributeTypes, - ), - 'joins' => array( - array( - 'table' => 'object_template_elements', - 'alias' => 'ObjectTemplateElement', - 'type' => 'RIGHT', - 'fields' => array('ObjectTemplateElement.object_relation', 'ObjectTemplateElement.type'), - 'conditions' => array('ObjectTemplate.id = ObjectTemplateElement.object_template_id') - ) - ), - 'group' => 'ObjectTemplate.id', - )); - - $templates = $this->ObjectTemplate->find('all', [ - 'recursive' => -1, - 'conditions' => ['id' => $potentialTemplateIds], - 'contain' => ['ObjectTemplateElement' => ['fields' => ['object_relation', 'type', 'multiple']]] - ]); - - foreach ($templates as $i => $template) { - $res = $this->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $attributes); - $templates[$i]['ObjectTemplate']['compatibility'] = $res['valid'] ? true : $res['missingTypes']; - $templates[$i]['ObjectTemplate']['invalidTypes'] = $res['invalidTypes']; - $templates[$i]['ObjectTemplate']['invalidTypesMultiple'] = $res['invalidTypesMultiple']; - } - return array('templates' => $templates, 'types' => $attributeTypes); + $attributeTypes = array_column(array_column($attributes, 'Attribute'), 'type'); + return $this->ObjectTemplate->fetchPossibleTemplatesBasedOnTypes($attributeTypes); } public function groupAttributesIntoObject(array $user, $event_id, array $object, $template, array $selected_attribute_ids, array $selected_object_relation_mapping, $hard_delete_attribute) diff --git a/app/Model/ObjectTemplate.php b/app/Model/ObjectTemplate.php index f82b89681..ef257d7d4 100644 --- a/app/Model/ObjectTemplate.php +++ b/app/Model/ObjectTemplate.php @@ -207,11 +207,69 @@ class ObjectTemplate extends AppModel } /** - * @param array $template - * @param array $attributes + * @param array $attributeTypes * @return array */ - public function checkTemplateConformityBasedOnTypes(array $template, array $attributes) + public function fetchPossibleTemplatesBasedOnTypes(array $attributeTypes) + { + $uniqueAttributeTypes = array_unique($attributeTypes, SORT_REGULAR); + $potentialTemplateIds = $this->find('column', array( + 'recursive' => -1, + 'fields' => array( + 'ObjectTemplate.id', + ), + 'conditions' => array( + 'ObjectTemplate.active' => true, + 'ObjectTemplateElement.type' => $uniqueAttributeTypes, + ), + 'joins' => array( + array( + 'table' => 'object_template_elements', + 'alias' => 'ObjectTemplateElement', + 'type' => 'RIGHT', + 'fields' => array('ObjectTemplateElement.object_relation', 'ObjectTemplateElement.type'), + 'conditions' => array('ObjectTemplate.id = ObjectTemplateElement.object_template_id') + ) + ), + 'group' => 'ObjectTemplate.id', + )); + + $templates = $this->find('all', [ + 'recursive' => -1, + 'conditions' => ['id' => $potentialTemplateIds], + 'contain' => ['ObjectTemplateElement' => ['fields' => ['object_relation', 'type', 'multiple']]] + ]); + + foreach ($templates as $i => $template) { + $res = $this->checkTemplateConformityBasedOnTypes($template, $attributeTypes); + $templates[$i]['ObjectTemplate']['compatibility'] = $res['valid'] ? true : $res['missingTypes']; + $templates[$i]['ObjectTemplate']['invalidTypes'] = $res['invalidTypes']; + $templates[$i]['ObjectTemplate']['invalidTypesMultiple'] = $res['invalidTypesMultiple']; + } + + usort($templates, function($a, $b) { + if ($a['ObjectTemplate']['id'] == $b['ObjectTemplate']['id']) { + return 0; + } else if (is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) { + return count($a['ObjectTemplate']['compatibility']) > count($b['ObjectTemplate']['compatibility']) ? 1 : -1; + } else if (is_array($a['ObjectTemplate']['compatibility']) && !is_array($b['ObjectTemplate']['compatibility'])) { + return 1; + } else if (!is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) { + return -1; + } else { // sort based on invalidTypes count + return count($a['ObjectTemplate']['invalidTypes']) > count($b['ObjectTemplate']['invalidTypes']) ? 1 : -1; + } + }); + + return array('templates' => $templates, 'types' => $uniqueAttributeTypes); + } + + /** + * @param array $template + * @param array $attributeTypes Array of attribute types to check, can contains multiple types + * @return array + */ + public function checkTemplateConformityBasedOnTypes(array $template, array $attributeTypes) { $to_return = array('valid' => true, 'missingTypes' => array()); if (!empty($template['ObjectTemplate']['requirements'])) { @@ -222,13 +280,7 @@ class ObjectTemplate extends AppModel if (!empty($template['ObjectTemplate']['requirements']['required'])) { foreach ($template['ObjectTemplate']['requirements']['required'] as $requiredField) { $requiredType = $elementsByObjectRelationName[$requiredField]['type']; - $found = false; - foreach ($attributes as $attribute) { - if ($attribute['Attribute']['type'] === $requiredType) { - $found = true; - break; - } - } + $found = in_array($requiredType, $attributeTypes, true); if (!$found) { $to_return = array('valid' => false, 'missingTypes' => array($requiredType)); } @@ -241,11 +293,8 @@ class ObjectTemplate extends AppModel foreach ($template['ObjectTemplate']['requirements']['requiredOneOf'] as $requiredField) { $requiredType = $elementsByObjectRelationName[$requiredField]['type'] ?? null; $allRequiredTypes[] = $requiredType; - foreach ($attributes as $attribute) { - if ($attribute['Attribute']['type'] === $requiredType) { - $found = true; - break; - } + if (!$found) { + $found = in_array($requiredType, $attributeTypes, true); } } if (!$found) { @@ -262,17 +311,17 @@ class ObjectTemplate extends AppModel $valid_types[$templateElement['type']] = $templateElement['multiple']; } $check_for_multiple_type = array(); - foreach ($attributes as $attribute) { - if (isset($valid_types[$attribute['Attribute']['type']])) { - if (!$valid_types[$attribute['Attribute']['type']]) { // is not multiple - if (isset($check_for_multiple_type[$attribute['Attribute']['type']])) { - $to_return['invalidTypesMultiple'][] = $attribute['Attribute']['type']; + foreach ($attributeTypes as $attributeType) { + if (isset($valid_types[$attributeType])) { + if (!$valid_types[$attributeType]) { // is not multiple + if (isset($check_for_multiple_type[$attributeType])) { + $to_return['invalidTypesMultiple'][] = $attributeType; } else { - $check_for_multiple_type[$attribute['Attribute']['type']] = 1; + $check_for_multiple_type[$attributeType] = 1; } } } else { - $to_return['invalidTypes'][] = $attribute['Attribute']['type']; + $to_return['invalidTypes'][] = $attributeType; } } $to_return['invalidTypes'] = array_unique($to_return['invalidTypes'], SORT_REGULAR);