chg: [internal] Faster adding tags to attributes

pull/7808/head
Jakub Onderka 2021-10-06 18:26:59 +02:00
parent 9260da8d0c
commit 8bee6de811
4 changed files with 80 additions and 66 deletions

View File

@ -2622,7 +2622,7 @@ class AttributesController extends AppController
);
$RearrangeTool = new RequestRearrangeTool();
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
$local = empty($this->params['named']['local']) ? 0 : 1;
$local = empty($this->request->params['named']['local']) ? 0 : 1;
if (!$this->request->is('post')) {
if ($id === false) {
throw new NotFoundException(__('Invalid attribute'));
@ -2660,10 +2660,7 @@ class AttributesController extends AppController
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
}
$tag_id_list = array();
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
$tag_id_list = array_column($tagCollection[0]['TagCollectionTag'], 'tag_id');
} else {
// try to parse json array
$tag_ids = json_decode($tag_id);
@ -2677,9 +2674,7 @@ class AttributesController extends AppController
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
}
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
$tag_id_list = array_column($tagCollection[0]['TagCollectionTag'], 'tag_id');
} else {
$tag_id_list[] = $tag_id;
}
@ -2704,90 +2699,68 @@ class AttributesController extends AppController
if (empty($tag_id_list)) {
$tag_id_list = array($tag_id);
}
$conditions = ['Tag.id' => $tag_id_list];
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array(0, $this->Auth->user('org_id'));
$conditions['Tag.user_id'] = array(0, $this->Auth->user('id'));
}
$tags = $this->Attribute->AttributeTag->Tag->find('list', array(
'conditions' => $conditions,
'fields' => ['Tag.id', 'Tag.name'],
));
$success = 0;
$fails = 0;
$this->Taxonomy = ClassRegistry::init('Taxonomy');
foreach ($idList as $id) {
$attributes = $this->Attribute->fetchAttributes(
$this->Auth->user(),
array(
'conditions' => array('Attribute.id' => $id, 'Attribute.deleted' => 0),
'flatten' => 1,
'contain' => array('Event.orgc_id')
)
);
if (empty($attributes)) {
$attribute = $this->Attribute->fetchAttributeSimple($this->Auth->user(), [
'conditions' => array('Attribute.id' => $id, 'Attribute.deleted' => 0),
]);
if (empty($attribute)) {
throw new NotFoundException(__('Invalid attribute'));
} else {
$attribute = $attributes[0];
}
$eventId = $attribute['Attribute']['event_id'];
$event = $this->Attribute->Event->find('first', array(
'conditions' => array('Event.id' => $eventId),
'recursive' => -1
));
if (!$this->__canModifyTag($event, $local)) {
if (!$this->__canModifyTag($attribute, $local)) {
$fails++;
continue;
}
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $eventId);
$this->Attribute->Event->insertLock($this->Auth->user(), $attribute['Event']['id']);
}
$changeTimestamp = false;
foreach ($tag_id_list as $tag_id) {
$conditions = ['Tag.id' => $tag_id];
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
$conditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
}
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
'conditions' => $conditions,
'recursive' => -1,
'fields' => array('Tag.name')
));
if (!$tag) {
if (!isset($tags[$tag_id])) {
// Tag not found or user don't have permission to add it.
$fails++;
continue;
}
$found = $this->Attribute->AttributeTag->find('first', array(
'conditions' => array(
'attribute_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (!empty($found)) {
$tagName = $tags[$tag_id];
$found = $this->Attribute->AttributeTag->hasAny([
'attribute_id' => $id,
'tag_id' => $tag_id,
]);
if ($found) {
// Tag is already assigned to given attribute.
$fails++;
continue;
}
$tagsOnAttribute = $this->Attribute->AttributeTag->find('all', array(
$tagsOnAttribute = $this->Attribute->AttributeTag->find('column', array(
'conditions' => array(
'AttributeTag.attribute_id' => $id,
'AttributeTag.local' => $local
'AttributeTag.local' => $local,
),
'contain' => 'Tag',
'fields' => array('Tag.name'),
'recursive' => -1
));
$exclusiveTestPassed = $this->Taxonomy->checkIfNewTagIsAllowedByTaxonomy($tag['Tag']['name'], Hash::extract($tagsOnAttribute, '{n}.Tag.name'));
$exclusiveTestPassed = $this->Taxonomy->checkIfNewTagIsAllowedByTaxonomy($tagName, $tagsOnAttribute);
if (!$exclusiveTestPassed) {
$fails++;
continue;
}
$this->Attribute->AttributeTag->create();
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $eventId, 'local' => $local))) {
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $attribute['Event']['id'], 'local' => $local))) {
if (!$local) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$result = $this->Attribute->Event->save($event);
$attribute['Attribute']['timestamp'] = $date->getTimestamp();
if ($attribute['Attribute']['object_id'] != 0) {
$this->Attribute->Object->updateTimestamp($attribute['Attribute']['object_id'], $date->getTimestamp());
}
$this->Attribute->save($attribute);
$changeTimestamp = true;
}
$log = ClassRegistry::init('Log');
$log->createLogEntry(
@ -2799,7 +2772,7 @@ class AttributesController extends AppController
'Attached%s tag (%s) "%s" to attribute (%s)',
$local ? ' local' : '',
$tag_id,
$tag['Tag']['name'],
$tagName,
$id
),
sprintf(
@ -2814,8 +2787,20 @@ class AttributesController extends AppController
$fails++;
}
}
if ($changeTimestamp) {
$attribute['Event']['published'] = 0;
$date = new DateTime();
$attribute['Event']['timestamp'] = $date->getTimestamp();
$result = $this->Attribute->Event->save($attribute['Event']);
$attribute['Attribute']['timestamp'] = $date->getTimestamp();
if ($attribute['Attribute']['object_id'] != 0) {
$this->Attribute->Object->updateTimestamp($attribute['Attribute']['object_id'], $date->getTimestamp());
}
$this->Attribute->save($attribute['Attribute']);
}
}
if ($fails == 0) {
if ($fails === 0) {
$message = __n('Tag added.', '%s tags added', $success, $success);
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $message, 'check_publish' => true)), 'status' => 200, 'type' => 'json'));
} else {
@ -2823,7 +2808,7 @@ class AttributesController extends AppController
if ($success > 0) {
$message .= __n(' However, %s tag was added.', ' However, %s tags were added.', $success, $success);
}
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $message)), 'status' => 200, 'type' => 'json'));
return new CakeResponse(array('body' => json_encode(array('saved' => false, 'errors' => $message)), 'status' => 200, 'type' => 'json'));
}
}
}

View File

@ -2669,6 +2669,30 @@ class Attribute extends AppModel
return $attribute;
}
/**
* @param array $user
* @param array $options
* @return array
*/
public function fetchAttributeSimple(array $user, array $options = [])
{
$query = [
'recursive' => -1,
'conditions' => $this->buildConditions($user),
'contain' => ['Event', 'Object'], // by default include Event and Object, because it is required for conditions
];
if (isset($options['conditions'])) {
$query['conditions']['AND'][] = $options['conditions'];
}
if (isset($options['fields'])) {
$query['fields'] = $options['fields'];
}
if (isset($options['contain'])) {
$query['contain'] = $options['contain'];
}
return $this->find('first', $query);
}
/**
* Fetches attributes that $user can see.
*

View File

@ -1155,14 +1155,19 @@ class MispObject extends AppModel
return true;
}
/**
* @param int $id
* @param false|int $timestamp
* @return array|bool|mixed|null
* @throws Exception
*/
public function updateTimestamp($id, $timestamp = false)
{
$date = new DateTime();
$object = $this->find('first', array(
'recursive' => -1,
'conditions' => array('Object.id' => $id)
));
$object['Object']['timestamp'] = $timestamp == false ? $date->getTimestamp() : $timestamp;
$object['Object']['timestamp'] = $timestamp === false ? time() : $timestamp;
$object['Object']['skip_zmq'] = 1;
$object['Object']['skip_kafka'] = 1;
$result = $this->save($object);

View File

@ -649,7 +649,7 @@ class Taxonomy extends AppModel
$prefixIsFree = true;
foreach ($tagNameList as $tagName) {
$tagShortened = $this->stripLastTagComponent($tagName);
if ($newTagShortened == $tagShortened) {
if ($newTagShortened === $tagShortened) {
$prefixIsFree = false;
break;
}