/** * Stores the tags to database * * @param eZContentObjectAttribute $attribute */ function store($attribute) { if (!($attribute instanceof eZContentObjectAttribute && is_numeric($attribute->attribute('id')))) { return; } $attributeID = $attribute->attribute('id'); $attributeVersion = $attribute->attribute('version'); $objectID = $attribute->attribute('contentobject_id'); $db = eZDB::instance(); $currentTime = time(); //get existing tags for object attribute $existingTagIDs = array(); $existingTags = $db->arrayQuery("SELECT DISTINCT keyword_id FROM eztags_attribute_link WHERE objectattribute_id = {$attributeID} AND objectattribute_version = {$attributeVersion}"); if (is_array($existingTags)) { foreach ($existingTags as $t) { $existingTagIDs[] = (int) $t['keyword_id']; } } //get tags to delete from object attribute $tagsToDelete = array(); $tempIDArray = array(); // if for some reason already existing tags are added with ID = 0 with fromString // check to see if they really exist, so we don't delete them by mistake foreach (array_keys($this->IDArray) as $key) { if ($this->IDArray[$key] == 0) { $existing = eZTagsObject::fetchList(array('keyword' => array('like', trim($this->KeywordArray[$key])), 'parent_id' => $this->ParentArray[$key])); if (is_array($existing) && !empty($existing)) { $tempIDArray[] = $existing[0]->attribute('id'); } } else { $tempIDArray[] = $this->IDArray[$key]; } } foreach ($existingTagIDs as $tid) { if (!in_array($tid, $tempIDArray)) { $tagsToDelete[] = $tid; } } //and delete them if (!empty($tagsToDelete)) { $dbString = $db->generateSQLINStatement($tagsToDelete, 'keyword_id', false, true, 'int'); $db->query("DELETE FROM eztags_attribute_link WHERE {$dbString} AND eztags_attribute_link.objectattribute_id = {$attributeID} AND eztags_attribute_link.objectattribute_version = {$attributeVersion}"); } //get tags that are new to the object attribute $newTags = array(); $tagsToLink = array(); foreach (array_keys($this->IDArray) as $key) { if (!in_array($this->IDArray[$key], $existingTagIDs)) { if ($this->IDArray[$key] == 0) { // We won't allow adding tags to the database that already exist, but instead, we link to the existing tags $existing = eZTagsObject::fetchList(array('keyword' => array('like', trim($this->KeywordArray[$key])), 'parent_id' => $this->ParentArray[$key])); if (is_array($existing) && !empty($existing)) { if (!in_array($existing[0]->attribute('id'), $existingTagIDs)) { $tagsToLink[] = $existing[0]->attribute('id'); } } else { $newTags[] = array('id' => $this->IDArray[$key], 'keyword' => $this->KeywordArray[$key], 'parent_id' => $this->ParentArray[$key]); } } else { $tagsToLink[] = $this->IDArray[$key]; } } } //we need to check if user really has access to tags/add, taking into account policy and subtree limits $attributeSubTreeLimit = $attribute->contentClassAttribute()->attribute(eZTagsType::SUBTREE_LIMIT_FIELD); $userLimitations = eZTagsTemplateFunctions::getSimplifiedUserAccess('tags', 'add'); if ($userLimitations['accessWord'] != 'no' && !empty($newTags)) { //first we need to fetch all locations user has access to $userLimitations = isset($userLimitations['simplifiedLimitations']['Tag']) ? $userLimitations['simplifiedLimitations']['Tag'] : array(); $allowedLocations = self::getAllowedLocations($attributeSubTreeLimit, $userLimitations); foreach ($newTags as $t) { //and then for each tag check if user can save in one of the allowed locations $parentTag = eZTagsObject::fetch($t['parent_id']); $pathString = $parentTag instanceof eZTagsObject ? $parentTag->attribute('path_string') : '/'; $depth = $parentTag instanceof eZTagsObject ? (int) $parentTag->attribute('depth') + 1 : 1; if (self::canSave($pathString, $allowedLocations)) { $db->query("INSERT INTO eztags ( parent_id, main_tag_id, keyword, depth, path_string, modified, remote_id ) VALUES ( " . $t['parent_id'] . ", 0, '" . $db->escapeString(trim($t['keyword'])) . "', {$depth}, '{$pathString}', 0, '" . eZTagsObject::generateRemoteID() . "' )"); $tagID = (int) $db->lastSerialID('eztags', 'id'); $db->query("UPDATE eztags SET path_string = CONCAT(path_string, CAST({$tagID} AS CHAR), '/') WHERE id = {$tagID}"); $pathArray = explode('/', trim($pathString, '/')); array_push($pathArray, $tagID); $db->query("UPDATE eztags SET modified = {$currentTime} WHERE " . $db->generateSQLINStatement($pathArray, 'id', false, true, 'int')); $tagsToLink[] = $tagID; if (class_exists('ezpEvent', false)) { ezpEvent::getInstance()->filter('tag/add', array('tag' => eZTagsObject::fetch($tagID), 'parentTag' => $parentTag)); } } } } //link tags to objects taking into account subtree limit if (!empty($tagsToLink)) { $dbString = $db->generateSQLINStatement($tagsToLink, 'id', false, true, 'int'); $tagsToLink = $db->arrayQuery("SELECT id, path_string FROM eztags WHERE {$dbString}"); if (is_array($tagsToLink) && !empty($tagsToLink)) { foreach ($tagsToLink as $t) { if ($attributeSubTreeLimit == 0 || $attributeSubTreeLimit > 0 && strpos($t['path_string'], '/' . $attributeSubTreeLimit . '/') !== false) { $db->query("INSERT INTO eztags_attribute_link ( keyword_id, objectattribute_id, objectattribute_version, object_id ) VALUES ( " . $t['id'] . ", {$attributeID}, {$attributeVersion}, {$objectID} )"); } } } } }