diff --git a/app/Model/Attribute.php b/app/Model/Attribute.php index 99830885d..236b9b7df 100644 --- a/app/Model/Attribute.php +++ b/app/Model/Attribute.php @@ -1944,6 +1944,9 @@ class Attribute extends AppModel $attribute['Attribute']['data'] = $encodedFile; } if ($options['includeDecayScore']) { + if (empty($attribute['Attribute']['to_ids'])) { + continue; // It only makes sense to consider IoCs for the decaying + } $this->DecayingModel = ClassRegistry::init('DecayingModel'); $include_full_model = isset($options['includeFullModel']) && $options['includeFullModel'] ? 1 : 0; if (empty($attribute['Attribute']['AttributeTag'])) { diff --git a/app/Model/DecayingModel.php b/app/Model/DecayingModel.php index 51d845de5..b1b6a6712 100644 --- a/app/Model/DecayingModel.php +++ b/app/Model/DecayingModel.php @@ -16,6 +16,9 @@ class DecayingModel extends AppModel ) ); + private $modelCache = []; + private $modelCacheForType = []; + private $__registered_model_classes = array(); // Proxy for already instantiated classes public $allowed_overrides = array('threshold' => 1, 'lifetime' => 1, 'decay_speed' => 1); @@ -263,6 +266,10 @@ class DecayingModel extends AppModel // - full attach Attribute types associated to the requested model public function fetchModel($user, $id, $full=true, $conditions=array(), $attach_editable=0) { + $cacheKey = sprintf('%s', $id); + if (isset($this->modelCache[$cacheKey])) { + return $this->modelCache[$cacheKey]; + } $conditions['id'] = $id; $searchOptions = array( 'conditions' => $conditions, @@ -290,6 +297,7 @@ class DecayingModel extends AppModel $decayingModel['DecayingModel']['attribute_types'] = $this->DecayingModelMapping->getAssociatedTypes($user, $decayingModel); } $decayingModel = $this->attachIsEditableByCurrentUser($user, $decayingModel); + $this->modelCache[$cacheKey] = $decayingModel; return $decayingModel; } @@ -612,11 +620,15 @@ class DecayingModel extends AppModel if ($model_id === false) { // fetch all allowed and associated models $associated_model_ids = $this->DecayingModelMapping->getAssociatedModels($user, $attribute['type'], true); $associated_model_ids = isset($associated_model_ids[$attribute['type']]) ? array_values($associated_model_ids[$attribute['type']]) : array(); - if (!empty($associated_model_ids)) { + if (isset($this->modelCacheForType[$attribute['type']])) { + $models = $this->modelCacheForType[$attribute['type']]; + } else if (!empty($associated_model_ids)) { $models = $this->fetchModels($user, $associated_model_ids, false, array('enabled' => true)); + $this->modelCacheForType[$attribute['type']] = $models; } } else { $models = $this->fetchModels($user, $model_id, false, array()); + $this->modelCacheForType[$attribute['type']] = $models; } foreach ($models as $model) { if (!empty($model_overrides)) { diff --git a/app/Model/DecayingModelMapping.php b/app/Model/DecayingModelMapping.php index 5005766ea..13577ef6e 100644 --- a/app/Model/DecayingModelMapping.php +++ b/app/Model/DecayingModelMapping.php @@ -25,6 +25,8 @@ class DecayingModelMapping extends AppModel ) ); + private $modelCache = []; + public function resetMappingForModel($new_model, $user) { if (empty($new_model['model_id'])) { throw new NotFoundException(__('No Decaying Model with the provided ID exists')); @@ -76,6 +78,10 @@ class DecayingModelMapping extends AppModel } public function getAssociatedModels($user, $attribute_type = false) { + $cacheKey = sprintf('%s', $attribute_type); + if (isset($this->modelCache[$cacheKey])) { + return $this->modelCache[$cacheKey]; + } $conditions = array( 'OR' => array( 'DecayingModel.org_id' => $user['org_id'], @@ -111,6 +117,7 @@ class DecayingModelMapping extends AppModel } $associated_models = Hash::combine($associated_models, '{n}.DecayingModelMapping.model_id', '{n}.DecayingModelMapping.model_id', '{n}.DecayingModelMapping.attribute_type'); $models = array_merge_recursive($associated_default_models, $associated_models); + $this->modelCache[$cacheKey] = $models; return $models; } diff --git a/app/Model/DecayingModelsFormulas/Base.php b/app/Model/DecayingModelsFormulas/Base.php index 3d3af1c7c..7073a7950 100644 --- a/app/Model/DecayingModelsFormulas/Base.php +++ b/app/Model/DecayingModelsFormulas/Base.php @@ -133,9 +133,9 @@ abstract class DecayingModelBase } if ($last_sighting_timestamp === false) { $this->Sighting = ClassRegistry::init('Sighting'); - $all_sightings = $this->Sighting->listSightings($user, $attribute['id'], 'attribute', false, 0, true); - if (!empty($all_sightings)) { - $last_sighting_timestamp = $all_sightings[0]['Sighting']['date_sighting']; + $last_sighting = $this->Sighting->getLastSightingForAttribute($attribute['id']); + if (!empty($last_sighting)) { + $last_sighting_timestamp = $last_sighting['Sighting']['date_sighting']; } elseif (!is_null($attribute['last_seen'])) { $last_sighting_timestamp = (new DateTime($attribute['last_seen']))->format('U'); } else { diff --git a/app/Model/Sighting.php b/app/Model/Sighting.php index 6f91868ba..3d5e1d0b1 100644 --- a/app/Model/Sighting.php +++ b/app/Model/Sighting.php @@ -1010,6 +1010,23 @@ class Sighting extends AppModel return $sightings; } + /** + * @param int $id + * @return array + */ + public function getLastSightingForAttribute($id): array + { + $sighting = $this->find('first', [ + 'conditions' => [ + 'Sighting.attribute_id' => $id, + 'Sighting.type' => 0, + ], + 'recursive' => -1, + 'order' => ['Sighting.date_sighting DESC'] + ]); + return empty($sighting) ? [] : $sighting; + } + /** * @param array $user * @param string $returnFormat