Example #1
0
 /**
  * Delete one or more tag, and all their instances if there are any left.
  *
  * @param    int|array    $tagids one tagid (int), or one array of tagids to delete
  * @return   bool     true on success, false otherwise
  */
 public static function delete_tags($tagids)
 {
     global $DB;
     if (!is_array($tagids)) {
         $tagids = array($tagids);
     }
     if (empty($tagids)) {
         return;
     }
     // Use the tagids to create a select statement to be used later.
     list($tagsql, $tagparams) = $DB->get_in_or_equal($tagids);
     // Store the tags and tag instances we are going to delete.
     $tags = $DB->get_records_select('tag', 'id ' . $tagsql, $tagparams);
     $taginstances = $DB->get_records_select('tag_instance', 'tagid ' . $tagsql, $tagparams);
     // Delete all the tag instances.
     $select = 'WHERE tagid ' . $tagsql;
     $sql = "DELETE FROM {tag_instance} {$select}";
     $DB->execute($sql, $tagparams);
     // Delete all the tag correlations.
     $sql = "DELETE FROM {tag_correlation} {$select}";
     $DB->execute($sql, $tagparams);
     // Delete all the tags.
     $select = 'WHERE id ' . $tagsql;
     $sql = "DELETE FROM {tag} {$select}";
     $DB->execute($sql, $tagparams);
     // Fire an event that these items were untagged.
     if ($taginstances) {
         // Save the system context in case the 'contextid' column in the 'tag_instance' table is null.
         $syscontextid = context_system::instance()->id;
         // Loop through the tag instances and fire a 'tag_removed'' event.
         foreach ($taginstances as $taginstance) {
             // We can not fire an event with 'null' as the contextid.
             if (is_null($taginstance->contextid)) {
                 $taginstance->contextid = $syscontextid;
             }
             // Trigger tag removed event.
             \core\event\tag_removed::create_from_tag_instance($taginstance, $tags[$taginstance->tagid]->name, $tags[$taginstance->tagid]->rawname, true)->trigger();
         }
     }
     // Fire an event that these tags were deleted.
     if ($tags) {
         $context = context_system::instance();
         foreach ($tags as $tag) {
             // Delete all files associated with this tag.
             $fs = get_file_storage();
             $files = $fs->get_area_files($context->id, 'tag', 'description', $tag->id);
             foreach ($files as $file) {
                 $file->delete();
             }
             // Trigger an event for deleting this tag.
             $event = \core\event\tag_deleted::create(array('objectid' => $tag->id, 'relateduserid' => $tag->userid, 'context' => $context, 'other' => array('name' => $tag->name, 'rawname' => $tag->rawname)));
             $event->add_record_snapshot('tag', $tag);
             $event->trigger();
         }
     }
     return true;
 }
Example #2
0
/**
 * This function will delete numerous tag instances efficiently.
 * This removes tag instances only. It doesn't check to see if it is the last use of a tag.
 *
 * @param array $instances An array of tag instance objects with the addition of the tagname and tagrawname
 *        (used for recording a delete event).
 */
function tag_bulk_delete_instances($instances)
{
    global $DB;
    $instanceids = array();
    foreach ($instances as $instance) {
        $instanceids[] = $instance->id;
    }
    // This is a multi db compatible method of creating the correct sql when using the 'IN' value.
    // $insql is the sql statement, $params are the id numbers.
    list($insql, $params) = $DB->get_in_or_equal($instanceids);
    $sql = 'id ' . $insql;
    $DB->delete_records_select('tag_instance', $sql, $params);
    // Now go through and record each tag individually with the event system.
    foreach ($instances as $instance) {
        // Trigger tag removed event (i.e. The tag instance has been removed).
        $event = \core\event\tag_removed::create(array('objectid' => $instance->id, 'contextid' => $instance->contextid, 'other' => array('tagid' => $instance->tagid, 'tagname' => $instance->name, 'tagrawname' => $instance->rawname, 'itemid' => $instance->itemid, 'itemtype' => $instance->itemtype)));
        unset($instance->name);
        unset($instance->rawname);
        $event->add_record_snapshot('tag_instance', $instance);
        $event->trigger();
    }
}
Example #3
0
 /**
  * This function will delete numerous tag instances efficiently.
  * This removes tag instances only. It doesn't check to see if it is the last use of a tag.
  *
  * @param array $instances An array of tag instance objects with the addition of the tagname and tagrawname
  *        (used for recording a delete event).
  */
 public function bulk_delete_instances($instances)
 {
     global $DB;
     $instanceids = array();
     foreach ($instances as $instance) {
         $instanceids[] = $instance->id;
     }
     // This is a multi db compatible method of creating the correct sql when using the 'IN' value.
     // $insql is the sql statement, $params are the id numbers.
     list($insql, $params) = $DB->get_in_or_equal($instanceids);
     $sql = 'id ' . $insql;
     $DB->delete_records_select('tag_instance', $sql, $params);
     // Now go through and record each tag individually with the event system.
     foreach ($instances as $instance) {
         // Trigger tag removed event (i.e. The tag instance has been removed).
         \core\event\tag_removed::create_from_tag_instance($instance, $instance->name, $instance->rawname, true)->trigger();
     }
 }
Example #4
0
/**
 * Delete one instance of a tag.  If the last instance was deleted, it will also delete the tag, unless its type is 'official'.
 *
 * @package  core_tag
 * @category tag
 * @access   public
 * @param    string $record_type the type of the record for which to remove the instance
 * @param    int    $record_id   the id of the record for which to remove the instance
 * @param    int    $tagid       the tagid that needs to be removed
 * @param    int    $userid      (optional) the userid
 * @return   bool   true on success, false otherwise
 */
function tag_delete_instance($record_type, $record_id, $tagid, $userid = null)
{
    global $DB;
    if (is_null($userid)) {
        $taginstance = $DB->get_record('tag_instance', array('tagid' => $tagid, 'itemtype' => $record_type, 'itemid' => $record_id));
    } else {
        $taginstance = $DB->get_record('tag_instance', array('tagid' => $tagid, 'itemtype' => $record_type, 'itemid' => $record_id, 'tiuserid' => $userid));
    }
    if ($taginstance) {
        // Get the tag.
        $tag = $DB->get_record('tag', array('id' => $tagid));
        $DB->delete_records('tag_instance', array('id' => $taginstance->id));
        // We can not fire an event with 'null' as the contextid.
        if (is_null($taginstance->contextid)) {
            $taginstance->contextid = context_system::instance()->id;
        }
        // Trigger tag removed event.
        $event = \core\event\tag_removed::create(array('objectid' => $taginstance->id, 'contextid' => $taginstance->contextid, 'other' => array('tagid' => $tag->id, 'tagname' => $tag->name, 'tagrawname' => $tag->rawname, 'itemid' => $taginstance->itemid, 'itemtype' => $taginstance->itemtype)));
        $event->add_record_snapshot('tag_instance', $taginstance);
        $event->trigger();
        // If there are no other instances of the tag then consider deleting the tag as well.
        if (!$DB->record_exists('tag_instance', array('tagid' => $tagid))) {
            // If the tag is a personal tag then delete it - don't delete official tags.
            if ($tag->tagtype == 'default') {
                tag_delete($tagid);
            }
        }
    } else {
        return false;
    }
    return true;
}
Example #5
0
 /**
  * Combines several other tags into this one
  *
  * Combining rules:
  * - current tag becomes the "main" one, all instances
  *   pointing to other tags are changed to point to it.
  * - if any of the tags is standard, the "main" tag becomes standard too
  * - all tags except for the current ("main") are deleted, even when they are standard
  *
  * @param core_tag_tag[] $tags tags to combine into this one
  */
 public function combine_tags($tags)
 {
     global $DB;
     $this->ensure_fields_exist(array('id', 'tagcollid', 'isstandard', 'name', 'rawname'), 'combine_tags');
     // Retrieve all tag objects, find if there are any standard tags in the set.
     $isstandard = false;
     $tagstocombine = array();
     $ids = array();
     $relatedtags = $this->get_manual_related_tags();
     foreach ($tags as $tag) {
         $tag->ensure_fields_exist(array('id', 'tagcollid', 'isstandard', 'tagcollid', 'name', 'rawname'), 'combine_tags');
         if ($tag && $tag->id != $this->id && $tag->tagcollid == $this->tagcollid) {
             $isstandard = $isstandard || $tag->isstandard;
             $tagstocombine[$tag->name] = $tag;
             $ids[] = $tag->id;
             $relatedtags = array_merge($relatedtags, $tag->get_manual_related_tags());
         }
     }
     if (empty($tagstocombine)) {
         // Nothing to do.
         return;
     }
     // Combine all manually set related tags, exclude itself all the tags it is about to be combined with.
     if ($relatedtags) {
         $relatedtags = array_map(function ($t) {
             return $t->name;
         }, $relatedtags);
         array_unique($relatedtags);
         $relatedtags = array_diff($relatedtags, [$this->name], array_keys($tagstocombine));
     }
     $this->set_related_tags($relatedtags);
     // Combine all correlated tags, exclude itself all the tags it is about to be combined with.
     $this->combine_correlated_tags($tagstocombine);
     // If any of the duplicate tags are standard, mark this one as standard too.
     if ($isstandard && !$this->isstandard) {
         $this->update(array('isstandard' => 1));
     }
     // Go through all instances of each tag that needs to be combined and make them point to this tag instead.
     // We go though the list one by one because otherwise looking-for-duplicates logic would be too complicated.
     foreach ($tagstocombine as $tag) {
         $params = array('tagid' => $tag->id, 'mainid' => $this->id);
         $mainsql = 'SELECT ti.*, t.name, t.rawname, tim.id AS alreadyhasmaintag ' . 'FROM {tag_instance} ti ' . 'LEFT JOIN {tag} t ON t.id = ti.tagid ' . 'LEFT JOIN {tag_instance} tim ON ti.component = tim.component AND ' . '    ti.itemtype = tim.itemtype AND ti.itemid = tim.itemid AND ' . '    ti.tiuserid = tim.tiuserid AND tim.tagid = :mainid ' . 'WHERE ti.tagid = :tagid';
         $records = $DB->get_records_sql($mainsql, $params);
         foreach ($records as $record) {
             if ($record->alreadyhasmaintag) {
                 // Item is tagged with both main tag and the duplicate tag.
                 // Remove instance pointing to the duplicate tag.
                 $tag->delete_instance_as_record($record, false);
                 $sql = "UPDATE {tag_instance} SET ordering = ordering - 1\n                            WHERE itemtype = :itemtype\n                        AND itemid = :itemid AND component = :component AND tiuserid = :tiuserid\n                        AND ordering > :ordering";
                 $DB->execute($sql, (array) $record);
             } else {
                 // Item is tagged only with duplicate tag but not the main tag.
                 // Replace tagid in the instance pointing to the duplicate tag with this tag.
                 $DB->update_record('tag_instance', array('id' => $record->id, 'tagid' => $this->id));
                 \core\event\tag_removed::create_from_tag_instance($record, $record->name, $record->rawname)->trigger();
                 $record->tagid = $this->id;
                 \core\event\tag_added::create_from_tag_instance($record, $this->name, $this->rawname)->trigger();
             }
         }
     }
     // Finally delete all tags that we combined into the current one.
     self::delete_tags($ids);
 }