There is no "add a tag" operation in Invision Community. Anything that tags content programmatically must pass the complete final set, or it silently destroys work someone did by hand.
What setTags() actually does
Db::i()->delete( 'core_tags', array( 'tag_aai_lookup=?', $aaiLookup ) );
foreach ( $set as $key => $tag )
{
try
{
Tag::load( $tag, 'tag_text' ); // must already exist
// ... insert
}
catch( \OutOfRangeException ) {} // unknown tags are dropped in silence
}
Three consequences:
- Every existing tag is deleted before anything is written.
- Unknown tags are discarded without error. Only tags already in the tag store can be applied.
- An array key of
'prefix'sets the item prefix rather than an ordinary tag.
Merging safely
$existing = $item->tags(); // non-prefix tags only
$prefix = $item->prefix(); // may be NULL
$set = array_values( array_unique( array_merge( $existing, $new ) ) );
if ( $prefix !== NULL )
{
// core runs array_unique() over the set; if the prefix text also appears as
// an ordinary tag, the numerically-keyed copy wins and the prefix is LOST
$set = array_values( array_filter( $set, function( $t ) use ( $prefix ) {
return mb_strtolower( $t ) !== mb_strtolower( $prefix );
} ) );
$set['prefix'] = $prefix;
}
$item->setTags( $set );
Also worth knowing
The site setting tags_force_lower makes tags() return lower-cased text that no longer matches how the tag is stored. Database collation hides this on lookup, but re-saving repeatedly will slowly rewrite every tag on the site to lower case. Map tags back to the tag store's own spelling before saving.
Related application: Auto Tagging — Auto Tagging merges what it adds with the tags already on an item, maps them back to the tag store's own spelling, and can be limited to items nobody has tagged by hand.
Recommended Comments