/** * Validate tags when saving a discussion. */ public function DiscussionModel_BeforeSaveDiscussion_Handler($Sender) { if (!C('Plugins.Tagging.Enabled')) { return; } $FormPostValues = GetValue('FormPostValues', $Sender->EventArguments, array()); $TagsString = trim(strtolower(GetValue('Tags', $FormPostValues, ''))); $NumTagsMax = C('Plugin.Tagging.Max', 5); // Tags can only contain unicode and the following ASCII: a-z 0-9 + # _ . if (StringIsNullOrEmpty($TagsString) && C('Plugins.Tagging.Required')) { $Sender->Validation->AddValidationResult('Tags', 'You must specify at least one tag.'); } else { $Tags = TagModel::SplitTags($TagsString); if (!TagModel::ValidateTags($Tags)) { $Sender->Validation->AddValidationResult('Tags', '@' . T('ValidateTag', 'Tags cannot contain spaces.')); } elseif (count($Tags) > $NumTagsMax) { $Sender->Validation->AddValidationResult('Tags', '@' . sprintf(T('You can only specify up to %s tags.'), $NumTagsMax)); } } }
/** * Add the tag input to the discussion form. * @param Gdn_Controller $Sender */ public function PostController_AfterDiscussionFormOptions_Handler($Sender) { if (in_array($Sender->RequestMethod, array('discussion', 'editdiscussion', 'question'))) { // Setup, get most popular tags $TagModel = TagModel::instance(); $Tags = $TagModel->GetWhere(array('Type' => array_keys($TagModel->defaultTypes())), 'CountDiscussions', 'desc', C('Plugins.Tagging.ShowLimit', 50))->Result(DATASET_TYPE_ARRAY); $TagsHtml = count($Tags) ? '' : T('No tags have been created yet.'); $Tags = Gdn_DataSet::Index($Tags, 'FullName'); ksort($Tags); // The tags must be fetched. if ($Sender->Request->IsPostBack()) { $tag_ids = TagModel::SplitTags($Sender->Form->GetFormValue('Tags')); $tags = TagModel::instance()->GetWhere(array('TagID' => $tag_ids))->ResultArray(); $tags = ConsolidateArrayValuesByKey($tags, 'FullName', 'TagID'); } else { // The tags should be set on the data. $tags = ConsolidateArrayValuesByKey($Sender->Data('Tags', array()), 'TagID', 'FullName'); $xtags = $Sender->Data('XTags', array()); foreach (TagModel::instance()->defaultTypes() as $key => $row) { if (isset($xtags[$key])) { $xtags2 = ConsolidateArrayValuesByKey($xtags[$key], 'TagID', 'FullName'); foreach ($xtags2 as $id => $name) { $tags[$id] = $name; } } } } echo '<div class="Form-Tags P">'; // Tag text box echo $Sender->Form->Label('Tags', 'Tags'); echo $Sender->Form->TextBox('Tags', array('data-tags' => json_encode($tags))); // Available tags echo Wrap(Anchor(T('Show popular tags'), '#'), 'span', array('class' => 'ShowTags')); foreach ($Tags as $Tag) { $TagsHtml .= Anchor(htmlspecialchars($Tag['FullName']), '#', 'AvailableTag', array('data-name' => $Tag['Name'], 'data-id' => $Tag['TagID'])) . ' '; } echo Wrap($TagsHtml, 'div', array('class' => 'Hidden AvailableTags')); echo '</div>'; } }
/** * * * @param $discussion_id * @param $tags * @param array $types * @param int $category_id * @param string $new_type * @throws Exception */ public function saveDiscussion($discussion_id, $tags, $types = array(''), $category_id = 0, $new_type = '') { // First grab all of the current tags. $all_tags = $current_tags = $this->getDiscussionTags($discussion_id, TagModel::IX_TAGID); // Put all the default tag types in the types if necessary. if (in_array('', $types)) { $types = array_merge($types, array_keys($this->defaultTypes())); $types = array_unique($types); } // Remove the types from the current tags that we don't need anymore. $current_tags = array_filter($current_tags, function ($row) use($types) { if (in_array($row['Type'], $types)) { return true; } return false; }); // Turn the tags into a nice array. if (is_string($tags)) { $tags = TagModel::SplitTags($tags); } $new_tags = array(); $tag_ids = array(); // See which tags are new and which ones aren't. foreach ($tags as $tag_id) { if (is_id($tag_id)) { $tag_ids[$tag_id] = true; } else { $new_tags[TagModel::tagSlug($tag_id)] = $tag_id; } } // See if any of the new tags actually exist by searching by name. if (!empty($new_tags)) { $found_tags = $this->getWhere(array('Name' => array_keys($new_tags)))->resultArray(); foreach ($found_tags as $found_tag_row) { $tag_ids[$found_tag_row['TagID']] = $found_tag_row; unset($new_tags[TagModel::TagSlug($found_tag_row['Name'])]); } } // Add any remaining tags that need to be added. if (Gdn::session()->checkPermission('Plugins.Tagging.Add')) { foreach ($new_tags as $name => $full_name) { $new_tag = array('Name' => trim(str_replace(' ', '-', strtolower($name)), '-'), 'FullName' => $full_name, 'Type' => $new_type, 'CategoryID' => $category_id, 'InsertUserID' => Gdn::session()->UserID, 'DateInserted' => Gdn_Format::toDateTime(), 'CountDiscussions' => 0); $tag_id = $this->SQL->options('Ignore', true)->insert('Tag', $new_tag); $tag_ids[$tag_id] = true; } } // Grab the tags so we can see more information about them. $save_tags = $this->getWhere(array('TagID' => array_keys($tag_ids)))->resultArray(); // Add any parent tags that may need to be added. foreach ($save_tags as $save_tag) { $parent_tag_id = val('ParentTagID', $save_tag); if ($parent_tag_id) { $tag_ids[$parent_tag_id] = true; } $all_tags[$save_tag['TagID']] = $save_tag; } // Remove tags that are already associated with the discussion. // $same_tag_ids = array_intersect_key($tag_ids, $current_tags); // $current_tags = array_diff_key($current_tags, $same_tag_ids); // $tag_ids = array_diff_key($tag_ids, $same_tag_ids); // Figure out the tags we need to add. $insert_tag_ids = array_diff_key($tag_ids, $current_tags); // Figure out the tags we need to remove. $delete_tag_ids = array_diff_key($current_tags, $tag_ids); $now = Gdn_Format::toDateTime(); // Insert the new tag mappings. foreach ($insert_tag_ids as $tag_id => $bool) { if (isset($all_tags[$tag_id])) { $insert_category_id = $all_tags[$tag_id]['CategoryID']; } else { $insert_category_id = $category_id; } $this->SQL->options('Ignore', true)->insert('TagDiscussion', array('DiscussionID' => $discussion_id, 'TagID' => $tag_id, 'DateInserted' => $now, 'CategoryID' => $insert_category_id)); } // Delete the old tag mappings. if (!empty($delete_tag_ids)) { $this->SQL->delete('TagDiscussion', array('DiscussionID' => $discussion_id, 'TagID' => array_keys($delete_tag_ids))); } // Increment the tag counts. if (!empty($insert_tag_ids)) { $this->SQL->update('Tag')->set('CountDiscussions', 'CountDiscussions + 1', false)->whereIn('TagID', array_keys($insert_tag_ids))->put(); } // Decrement the tag counts. if (!empty($delete_tag_ids)) { $this->SQL->update('Tag')->set('CountDiscussions', 'CountDiscussions - 1', false)->whereIn('TagID', array_keys($delete_tag_ids))->put(); } }