Finally I have discovered how to do this satisfactorily.
My requirement is to be able to create some tags - for example when installing xbCulture Components or when converting xbRefs Text References to Tag References in xbRefMan. These tags need to have a description and parent set as well as just a title so the simple function in TagsHelper::createTagsFromField(array())
does not cut the mustard. It only lets you create simple tags with just a title, and has a weird syntax whereby the title string has to be prefixed with #new#
The answer is to get a tags table object and use the bind()
, check()
and store()
table functions. In addition to get the parent_id set correctly you have to call the setLocation()
function before store() - this will set up the lft, rgt, and level fields but not the path field. To do that you have to rebuildPath($id)
with the new tag id after store().
So putting it all together with some error checking and detecting if a tag with the same alias already exists in a Component Helper function to which I can pass the data for the new tag as an array I get this:
public static function createTag(array $tagdata) {
Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_tags/tables');
$app = Factory::getApplication();
//check if alias already exists (dupe id)
$alias = $tagdata['title'];
$alias = ApplicationHelper::stringURLSafe($alias);
if (trim(str_replace('-', '', $alias)) == '') {
$alias = Factory::getDate()->format('Y-m-d-H-i-s');
}
$db = Factory::getDBO();
$query = $db->getQuery(true);
$query->select('id')->from($db->quoteName('#__tags'))->where($db->quoteName('alias').' = '.$db->quote($alias));
$db->setQuery($query);
$id = $db->loadResult();
if ($id>0) {
$app->enqueueMessage('Tag with alias '.$alias.' already exists with id '.$id,'Warning');
return $id;
}
$table = Table::getInstance('Tag', 'TagsTable', array());
// Bind data
if (!$table->bind($tagdata)) {
$app->enqueueMessage($table->getError(),'Error');
return false;
}
// Check the data.
if (!$table->check()) {
$app->enqueueMessage($table->getError(),'Error');
return false;
}
// set the parent details
$table->setLocation($tagdata['parent_id'], 'last-child'); //no error reporting from this one
// Store the data.
if (!$table->store()){
$app->enqueueMessage($table->getError(),'Error');
return false;
}
if (!$table->rebuildPath($table->id)) {
$app->enqueueMessage($table->getError(),'Error');
return false;
}
$app->enqueueMessage('New tag '.$tagdata['title'].' created with id '.$table->id);
return $table->id;
}
The data array is an assoc array and must include 'title', 'parent_id' (=1 if no parent) and 'published' (=1 for published as usual). 'description' is optional, as are all the other fields like publilication data will get set automatically if needed.
It seems to work ok.
Comments powered by CComment