3 * Table Definition for profile_tag
6 class Profile_tag extends Managed_DataObject
8 public $__table = 'profile_tag'; // table name
9 public $tagger; // int(4) primary_key not_null
10 public $tagged; // int(4) primary_key not_null
11 public $tag; // varchar(64) primary_key not_null
12 public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
14 public static function schemaDef()
19 'tagger' => array('type' => 'int', 'not null' => true, 'description' => 'user making the tag'),
20 'tagged' => array('type' => 'int', 'not null' => true, 'description' => 'profile tagged'),
21 'tag' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'hash tag associated with this notice'),
22 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date the tag was added'),
24 'primary key' => array('tagger', 'tagged', 'tag'),
25 'foreign keys' => array(
26 'profile_tag_tagger_fkey' => array('profile', array('tagger' => 'id')),
27 'profile_tag_tagged_fkey' => array('profile', array('tagged' => 'id')),
28 'profile_tag_tag_fkey' => array('profile_list', array('tag' => 'tag')),
31 'profile_tag_modified_idx' => array('modified'),
32 'profile_tag_tagger_tag_idx' => array('tagger', 'tag'),
33 'profile_tag_tagged_idx' => array('tagged'),
40 return array('tagger,tag' => 'profile_list:tagger,tag');
45 return Profile_list::pkeyGet(array('tagger' => $this->tagger, 'tag' => $this->tag));
48 static function getSelfTagsArray(Profile $target)
50 return self::getTagsArray($target->getID(), $target->getID(), $target);
53 static function setSelfTags(Profile $target, array $newtags, array $privacy=array())
55 return self::setTags($target->getID(), $target->getID(), $newtags, $privacy);
58 static function getTags($tagger, $tagged, $auth_user=null) {
60 $profile_list = new Profile_list();
63 if (!($auth_user instanceof User ||
64 $auth_user instanceof Profile) ||
65 ($auth_user->id !== $tagger)) {
67 $profile_list->private = false;
71 $key = sprintf('profile_tag:tagger_tagged_privacy:%d-%d-%d', $tagger, $tagged, $include_priv);
72 $tags = Profile_list::getCached($key);
73 if ($tags !== false) {
77 $qry = 'select profile_list.* from profile_list left join '.
78 'profile_tag on (profile_list.tag = profile_tag.tag and '.
79 'profile_list.tagger = profile_tag.tagger) where '.
80 'profile_tag.tagger = %d and profile_tag.tagged = %d ';
81 $qry = sprintf($qry, $tagger, $tagged);
84 $qry .= ' and profile_list.private = 0';
87 $profile_list->query($qry);
89 Profile_list::setCache($key, $profile_list);
94 static function getTagsArray($tagger, $tagged, Profile $scoped=null)
96 $ptag = new Profile_tag();
98 $qry = sprintf('select profile_tag.tag '.
99 'from profile_tag join profile_list '.
100 ' on (profile_tag.tagger = profile_list.tagger ' .
101 ' and profile_tag.tag = profile_list.tag) ' .
102 'where profile_tag.tagger = %d ' .
103 'and profile_tag.tagged = %d ',
106 if (!$scoped instanceof Profile || $scoped->getID() !== $tagger) {
107 $qry .= 'and profile_list.private = 0';
114 while ($ptag->fetch()) {
115 $tags[] = $ptag->tag;
121 static function setTags($tagger, $tagged, array $newtags, array $privacy=array()) {
123 $newtags = array_unique($newtags);
124 $oldtags = self::getTagsArray($tagger, $tagged, Profile::getByID($tagger));
126 $ptag = new Profile_tag();
128 // Delete stuff that's in old and not in new
130 $to_delete = array_diff($oldtags, $newtags);
132 // Insert stuff that's in new and not in old
134 $to_insert = array_diff($newtags, $oldtags);
136 foreach ($to_delete as $deltag) {
137 self::unTag($tagger, $tagged, $deltag);
140 foreach ($to_insert as $instag) {
141 $private = isset($privacy[$instag]) ? $privacy[$instag] : false;
142 self::setTag($tagger, $tagged, $instag, null, $private);
148 static function setTag($tagger, $tagged, $tag, $desc=null, $private=false) {
150 $ptag = Profile_tag::pkeyGet(array('tagger' => $tagger,
154 # if tag already exists, return it
155 if ($ptag instanceof Profile_tag) {
159 $tagger_profile = Profile::getByID($tagger);
160 $tagged_profile = Profile::getByID($tagged);
162 if (Event::handle('StartTagProfile', array($tagger_profile, $tagged_profile, $tag))) {
164 if (!$tagger_profile->canTag($tagged_profile)) {
165 // TRANS: Client exception thrown trying to set a tag for a user that cannot be tagged.
166 throw new ClientException(_('You cannot tag this user.'));
169 $tags = new Profile_list();
170 $tags->tagger = $tagger;
171 $count = (int) $tags->count('distinct tag');
173 if ($count >= common_config('peopletag', 'maxtags')) {
174 // TRANS: Client exception thrown trying to set more tags than allowed.
175 throw new ClientException(sprintf(_('You already have created %d or more tags ' .
176 'which is the maximum allowed number of tags. ' .
177 'Try using or deleting some existing tags.'),
178 common_config('peopletag', 'maxtags')));
181 $plist = new Profile_list();
182 $plist->query('BEGIN');
184 $profile_list = Profile_list::ensureTag($tagger, $tag, $desc, $private);
186 if ($profile_list->taggedCount() >= common_config('peopletag', 'maxpeople')) {
187 // TRANS: Client exception thrown when trying to add more people than allowed to a list.
188 throw new ClientException(sprintf(_('You already have %1$d or more people in list %2$s, ' .
189 'which is the maximum allowed number. ' .
190 'Try unlisting others first.'),
191 common_config('peopletag', 'maxpeople'), $tag));
194 $newtag = new Profile_tag();
196 $newtag->tagger = $tagger;
197 $newtag->tagged = $tagged;
200 $result = $newtag->insert();
203 common_log_db_error($newtag, 'INSERT', __FILE__);
204 $plist->query('ROLLBACK');
209 $plist->query('COMMIT');
210 Event::handle('EndTagProfile', array($newtag));
211 } catch (Exception $e) {
213 $profile_list->delete();
217 $profile_list->taggedCount(true);
218 self::blowCaches($tagger, $tagged);
224 static function unTag($tagger, $tagged, $tag) {
225 $ptag = Profile_tag::pkeyGet(array('tagger' => $tagger,
232 if (Event::handle('StartUntagProfile', array($ptag))) {
233 $orig = clone($ptag);
234 $result = $ptag->delete();
235 if ($result === false) {
236 common_log_db_error($this, 'DELETE', __FILE__);
239 Event::handle('EndUntagProfile', array($orig));
240 $profile_list = Profile_list::pkeyGet(array('tag' => $tag, 'tagger' => $tagger));
241 if (!empty($profile_list)) {
242 $profile_list->taggedCount(true);
244 self::blowCaches($tagger, $tagged);
249 // @fixme: move this to Profile_list?
250 static function cleanup($profile_list) {
251 $ptag = new Profile_tag();
252 $ptag->tagger = $profile_list->tagger;
253 $ptag->tag = $profile_list->tag;
256 while($ptag->fetch()) {
257 if (Event::handle('StartUntagProfile', array($ptag))) {
258 $orig = clone($ptag);
259 $result = $ptag->delete();
261 common_log_db_error($this, 'DELETE', __FILE__);
263 Event::handle('EndUntagProfile', array($orig));
269 static function moveTag($orig, $new) {
270 $tags = new Profile_tag();
271 $qry = 'UPDATE profile_tag SET ' .
272 'tag = "%s", tagger = "%s" ' .
273 'WHERE tag = "%s" ' .
275 $result = $tags->query(sprintf($qry,
276 $tags->escape($new->tag),
277 $tags->escape($new->tagger),
278 $tags->escape($orig->tag),
279 $tags->escape($orig->tagger)));
281 if ($result === false) {
282 common_log_db_error($tags, 'UPDATE', __FILE__);
283 throw new Exception('Could not move Profile_tag, see db log for details.');
288 static function blowCaches($tagger, $tagged) {
289 foreach (array(0, 1) as $perm) {
290 self::blow(sprintf('profile_tag:tagger_tagged_privacy:%d-%d-%d', $tagger, $tagged, $perm));
295 // Return profiles with a given tag
296 static function getTagged($tagger, $tag) {
297 $profile = new Profile();
298 $profile->query('SELECT profile.* ' .
299 'FROM profile JOIN profile_tag ' .
300 'ON profile.id = profile_tag.tagged ' .
301 'WHERE profile_tag.tagger = ' . $profile->escape($tagger) . ' ' .
302 'AND profile_tag.tag = "' . $profile->escape($tag) . '" ');
304 while ($profile->fetch()) {
305 $tagged[] = clone($profile);
312 $result = parent::insert();
314 self::blow('profile_list:tagged_count:%d:%s',
321 function delete($useWhere=false)
323 $result = parent::delete($useWhere);
324 if ($result !== false) {
325 self::blow('profile_list:tagged_count:%d:%s',