# sfDoctrineActAsTaggablePlugin #
## Introduction ##
This behavior permits to attach tags to Doctrine objects. It includes tag-clouds generation and helpers to display these clouds.
[[Image(sfPropelActAsTaggableBehaviorPlugin.png)]]
## Features ##
* add/remove tag(s) on an object
* multi-tags object search
* multi-models selection
* tag cloud generation
* related tags handling
* unit-tested for model
* [machine tags](http://www.flickr.com/groups/api/discuss/72157594497877875/) support (also called "triple tags")
* jQuery-based typeahead for tags (optional)
* easy tags fixtures loading NOT YET
## Upgrade Note ##
Prior to my svn commit of 2009-08-03, the typeahead support inserted nonbreaking
spaces, which some web browsers actually submitted even though they were part
of plaintext elements. This has been fixed.
You may have existing tag databases with what appear to be duplicate tags due
to the existence of "Bob Smith" (with a normal space) and "Bob Smith"
(with a nonbreaking space) side by side.
The following MySQL command will clean this up:
update tagging set tag_id =
(select id from tag where tag.name =
trim(replace((select name from tag where tag.id = tag_id),
char(160), ' ')));
## Philosophy of the stuff ##
* taggable models must have a primary key
* tags are saved when the object is saved, not before
* one object cannot be tagged twice with the same tag. When trying to use twice the same tag on one object, the second tagging will be ignored
* the tags associated to one taggable object are only loaded when necessary. Then they are cached.
* once created, tags never change in the Tag table. When using replaceTag(), a new tag is created if necessary, but the old one is not deleted.
## Get it installed ##
* go to your project's root
* Install the plugin:
./symfony plugin-install http://svn.symfony-project.com/plugins/sfDoctrineActAsTaggablePlugin/trunk
* edit your schema.yml and add
templates: [Taggable] to model you want to be taggable
* rebuild the model:
./symfony doctrine-build-all
* clear cache:
./symfony cc
## Usage ##
### Attaching tags to a taggable object ###
Consider a Doctrine "Post" class:
addTag('toto');
$post->addTag('tata, tutu');
$post->addTag(array('Titi', 'Gros Minet'));
$post->save();
?>
The plugin supports [machine tags](http://www.flickr.com/groups/api/discuss/72157594497877875/):
addTag('iso:isbn=123456789');
$post->save();
// assume City is a taggable class
$city = new City();
$city->addTag('geo:lat=47.3456');
$city->save();
By default, the plugin will allow to attach several triple tags with the same namespaces and key for one given object. That is, you could attach the tags ``geo:lat=36.5`` and ``geo:lat=43.2`` to the same object. If this behavior doesn't make you happy, you may want to tweak the plugin''s configuration in the ``app.yml`` file of your project:
all:
sfDoctrineActAsTaggablePlugin:
triple_distinct: true
### Retrieving one object's tags ###
It is possible to retrieve tags from a taggable object:
#!php
find(1);
$tags = $post->getTags();
foreach ($tags as $tag)
{
echo $tag.'
';
}
If you want to retrieve only the triple tags of a certain namespace, you can
pass some options to the ``getTags()`` method:
#!php
find(1);
$tags = $post->getTags(array('is_triple' => true,
'namespace' => 'geo',
'return' => 'value'));
foreach ($tags as $tag)
{
echo $tag.'
';
}
The getTags() method may accept up to 5 parameters:
* ``is_triple``: whether or not the returned tags should be triple tags only
* in case this option has been defined, the other options are available:
* ``namespace``: namespace of the returned triple tags
* ``key``: key of the returned triple tags
* ``value``: value of the returned triple tags
* ``tag``: complete triple-tag string of the returned triple tags
* ``return``: format of the returned result:
* By default, selecting triple tags will return an array of tags, in which each tag is represented by an array of the form [complete tag string, namespace, key, value].
* If the ``return`` option has the value ``namespace``, ``key`` or ``value``, the ``getTags()`` method will only return the namespaces, keys or values list.
### Removing one object's tags ###
Of course, tags can also be removed:
#!php
find(1);
$post->removeTag('toto');
$post->removeTag('toto, tutu');
$post->removeAllTags();
### Setting one object's tags ###
All the tags of an object can be set or replaced at once, using the methode
``setTags()``:
#!php
find(1);
$post->setTags('toto, tutu');
$post->save();
This is particularly useful when using [File Syntax fixtures](http://www.symfony-project.org/book/1_0/16-Application-Management-Tools#Fixture)
in a project, as it permits to attach tags to the objects a pretty straight way:
Post:
first_post:
title: My first memories
tags: memories, sleeping, bed
second_post:
title: Things got worse
tags: death, memories, personnal
### Retrieving objects, based on their tags ###
The plugin proposes several methods for retrieving objects given their tags.
These methods are all located in the ``PluginTagTable`` class:
#!php
true, 'namespace' => 'geo'));
$tutu_toto_objects = PluginTagTable::getObjectTaggedWith('tutu, toto', array('model' => 'Post'));
// it is als possible to select objects tagged with certain types of triple tags
// in this special case, the first "tags" parameter is useless. For instance,
// this line will return all the objects that have a triple tag in the namespace
// "geo":
$tutu_toto_objects = PluginTagTable::getObjectTaggedWith(array(), array('namespace' => 'geo'));
// gets a criteria that permits to select objects tagged with one or several
// specific tags
$criteria = PluginTagTable::getObjectTaggedWithQuery('Post', 'tutu, toto');
$criteria->addWhere('post.published = true');
$posts = $q->execute();
// gets objects that are tagged with a certain number of tags within a set of
// tags. For instance, the following line returns all the object tagged with at
// least two of the following tags: toto, tutu, tata, titi
$objects = PluginTagTable::getObjectTaggedWith('tutu, toto, tata, titi',
array('nb_common_tags' => 2));
The methods ``PluginTagTable::getRelatedTags()``, ``PluginTagTable::getObjectTaggedWith()``, and ``PluginTagTable::getObjectTaggedWithQuery()`` accept one additional parameter, "``nb_common_tags``", that permits to select objects that share a certain number of tags in common with the given tags list. For instance:
#!php
2));
### Tags cloud generation ###
The plugin also proposes methods and helpers for generating tags cloud:
#!php
'Post'));
// displays the related tags cloud, using the route "@post_tags" with the
// request parameter "tags". Please note that there is no %s in the route,
// on the contrary to the tag_cloud() helper
echo related_tag_cloud($tags, '@post_tags?tags=', 'toto,tutu');
This helper accepts several options:
* ``add``: text to be used, after each tag, as a link for adding this tag to the current selection
* ``class``: class of the tags cloud. By default, the class "tags-cloud" is used
You might also want to display the tags of one item. The ``tag_list()`` helper is done for this:
#!php
getTags();
echo tag_list($tags, '@tag?tag=');
This helper accepts several options:
* ``class``: class of the tags list. By default, the class "tags-list" is used
* ``ordered``: by default, the helper will generate an unordered list (HTML ``