/[drupal]/contributions/modules/facebook_status/facebook_status_tags.module
ViewVC logotype

Contents of /contributions/modules/facebook_status/facebook_status_tags.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Sun May 17 04:02:11 2009 UTC (6 months, 1 week ago) by icecreamyou
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--2
File MIME type: text/x-php
#437522 form wasn't cached with caching turned off on site (thanks katbailey)
Changed help text for some settings
Moved maximum status length setting from Advanced to General settings page
Added an open API for users with the 'view all statuses' permission in XML, JSON, and REST
Documented open API
Added submodule that allows referencing users with @username and taxonomy terms (including creation of new ones) with #termname.
Documented submodule
Added Views integration for submodule
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 * Converts @usernames to themed usernames and #hashtags to themed taxonomy terms on Facebook-style Statuses.
7 */
8
9 /**
10 * In this file:
11 * - "Tag" means a reference, like @username or #hashtag.
12 * - "Term" means a taxonomy term.
13 */
14
15 //=============
16 //DRUPAL HOOKS.
17 //=============
18
19 /**
20 * Implementation of hook_help().
21 */
22 function facebook_status_tags_help($path, $arg) {
23 if ($path == 'admin/help#facebook_status_tags') {
24 return t('Modifies Facebook-style Statuses on display to replace @username references with the themed username and #hashtags with taxonomy terms. ') .
25 t('Please see the <a href="http://drupal.org/project/facebook_status" rel="nofollow">Facebook-style Statuses project page</a> for more information.');
26 }
27 }
28
29 /**
30 * Implementation of hook_form_FORM_ID_alter().
31 */
32 function facebook_status_tags_form_facebook_status_admin_advanced_alter(&$form, &$form_state) {
33 if (module_exists('taxonomy')) {
34 $options = array('-1' => t('None'));
35 $vocabularies = taxonomy_get_vocabularies();
36 foreach ($vocabularies as $vocabulary) {
37 $options[$vocabulary->vid] = check_plain($vocabulary->name);
38 }
39 $form['facebook_status_tags_vid'] = array(
40 '#type' => 'select',
41 '#title' => t('Vocabulary for #hashtags'),
42 '#default_value' => variable_get('facebook_status_tags_vid', -1),
43 '#options' => $options,
44 '#weight' => -1,
45 );
46 $form['facebook_status_tags_url'] = array(
47 '#type' => 'textfield',
48 '#title' => t('Location of status-term pages'),
49 '#description' => t('Can be an absolute or relative URL. Use the tokens [term-id] and [term-name]. Use Views to build the listing (a default one is provided).'),
50 '#default_value' => variable_get('facebook_status_tags_url', 'statuses/term/[term-id]'),
51 '#weight' => -1,
52 );
53 return $form;
54 }
55 }
56
57 //====
58 //API.
59 //====
60
61 /**
62 * Gets statuses that have a given tag by tag name.
63 *
64 * @param $tag
65 * The taxonomy term or username which retrieved statuses must contain.
66 * @param $type
67 * The type of tag: 'user' or 'term.'
68 * @param $count
69 * The number of statuses to retrieve, starting with the most recent one. If
70 * zero, all relevant statuses are returned.
71 * @param $uid
72 * If zero, has no effect. If a positive integer, restricts results to
73 * statuses by the user with that UID. If an array of positive integers,
74 * restricts results to statuses by users with a UID in the array.
75 * @return
76 * An array of status objects.
77 */
78 function facebook_status_tags_get_statuses_by_tag($tag, $type = 'term', $count = 1, $uid = 0) {
79 $params = array($tag, $type);
80 if ($uid == 0) {
81 if ($type == 'term') {
82 $sql = "SELECT fbst.sid FROM {facebook_status_tags} fbst INNER JOIN {term_data} td ON fbst.rid = td.tid WHERE td.name = '%s' AND fbst.type = '%s'";
83 }
84 else if ($type == 'user') {
85 $sql = "SELECT fbst.sid FROM {facebook_status_tags} fbst INNER JOIN {users} u ON fbst.rid = u.uid WHERE u.name = '%s' AND fbst.type = '%s'";
86 }
87 }
88 else {
89 if (is_numeric($uid)) {
90 $uid = array($uid);
91 }
92 $params = array_merge($params, $uid);
93 if ($type == 'term') {
94 $sql = "SELECT fbst.sid FROM {facebook_status_tags} fbst INNER JOIN {term_data} td ON fbst.rid = td.tid INNER JOIN {facebook_status} fb ON fbst.sid = fb.sid
95 WHERE td.name = '%s' AND fbst.type = '%s' AND (";
96 }
97 else if ($type == 'user') {
98 $sql = "SELECT fbst.sid FROM {facebook_status_tags} fbst INNER JOIN {users} u ON fbst.rid = u.uid INNER JOIN {facebook_status} fb ON fbst.sid = fb.sid
99 WHERE u.name = '%s' AND fbst.type = '%s' AND (";
100 }
101 $sql .= implode(' OR ', array_fill(0, count($uid), 'fb.uid = %d'));
102 $sql .= ')';
103 }
104 if ($count) {
105 $result = db_query_range($sql, $params, 0, $count);
106 }
107 else {
108 $result = db_query($sql, $params);
109 }
110 $statuses = array();
111 while ($sid = db_fetch_object($result)) {
112 $statuses[] = facebook_status_load($sid->sid);
113 }
114 return $statuses;
115 }
116
117 /**
118 * Gets statuses that have a given tag by Term ID or User ID.
119 *
120 * @param $rid
121 * The Term ID of tags or the User ID of users which retrieved statuses must
122 * reference.
123 * @param $type
124 * The type of reference: 'user' or 'term.'
125 * @param $count
126 * The number of statuses to retrieve, starting with the most recent one. If
127 * zero, all relevant statuses are returned.
128 * @param $uid
129 * If zero, has no effect. If a positive integer, restricts results to
130 * statuses by the user with that UID. If an array of positive integers,
131 * restricts results to statuses by users with a UID in the array.
132 * @return
133 * An array of status objects.
134 */
135 function facebook_status_tags_get_statuses($rid, $type = 'term', $count = 1, $uid = 0) {
136 $params = array($rid, $type);
137 if ($uid == 0) {
138 $sql = "SELECT sid FROM {facebook_status_tags} WHERE rid = %d AND type = '%s'";
139 }
140 else {
141 if (is_numeric($uid)) {
142 $uid = array($uid);
143 }
144 $params = array_merge($params, $uid);
145 $sql = "SELECT fbst.sid FROM {facebook_status_tags} fbst INNER JOIN {facebook_status} fb ON fbst.sid = fb.sid WHERE fbst.rid = %d AND fbst.type = '%s' AND (";
146 $sql .= implode(' OR ', array_fill(0, count($uid), 'fb.uid = %d'));
147 $sql .= ')';
148 }
149 if ($count) {
150 $result = db_query_range($sql, $params, 0, $count);
151 }
152 else {
153 $result = db_query($sql, $params);
154 }
155 $statuses = array();
156 while ($sid = db_fetch_object($result)) {
157 $statuses[] = facebook_status_load($sid->sid);
158 }
159 return $statuses;
160 }
161
162 /**
163 * Determines whether a given status has a given reference.
164 *
165 * @param $sid
166 * The Status ID of the status being tested.
167 * @param $rid
168 * The Term ID or User ID of the reference being tested.
169 * @param $type
170 * The type of reference: 'user' or 'term.'
171 * @return
172 * 1 if the status has the reference or 0 if it does not.
173 */
174 function facebook_status_tags_status_has_tag($sid, $rid, $type = 'term') {
175 return db_result(db_query("SELECT COUNT(*) FROM {facebook_status_tags} WHERE sid = %d AND rid = %d AND type = '%s'", $sid, $rid, $type));
176 }
177
178 /**
179 * Gets the tags that a given status has.
180 *
181 * @param $sid
182 * The Status ID of the status for which to retrieve a tag.
183 * @param $type
184 * The type of reference: 'user' or 'term.'
185 * @return
186 * An array of term objects or user objects.
187 */
188 function facebook_status_tags_get_status_tags($sid, $type = 'term') {
189 $result = db_query("SELECT rid FROM {facebook_status_tags} WHERE sid = %d AND type = '%s'", $sid, $type);
190 $rids = array();
191 while ($rid = db_fetch_object($result)) {
192 if ($type == 'term') {
193 $rids[] = taxonomy_get_term($rid->rid);
194 }
195 else if ($type == 'user') {
196 $rids[] = user_load(array('uid' => $rid->rid));
197 }
198 }
199 return $rids;
200 }
201
202 //=================
203 //HELPER FUNCTIONS.
204 //=================
205
206 /**
207 * Replaces tags with a themed version.
208 * Will not work on tags containing $op, a space, or an apostrophe.
209 *
210 * @param $text
211 * The text in which to replace usernames.
212 * @param $op
213 * The character that indicates that the subsequent text could be a username.
214 * Use the 'at' character (@) for usernames and the 'hash' character (#) for
215 * taxonomy terms.
216 * @return
217 * The filtered text.
218 */
219 function _facebook_status_tags_filter($text, $op = '@') {
220 $pattern = '/([\s]'. $op .'.+\b)|(^'. $op .'.+\b)/U';
221 preg_match_all($pattern, $text, $matches);
222
223 $links = array();
224 foreach ($matches[0] as $match) {
225 if ($op == '@') {
226 $account = user_load(array('name' => drupal_substr(trim($match), 1)));
227 }
228 else if ($op == '#' && module_exists('taxonomy') && variable_get('facebook_status_tags_vid', -1) != -1) {
229 $term = _facebook_status_tags_get_term(drupal_substr(trim($match), 1));
230 }
231 $link = $op;
232 if (drupal_substr($match, 0, 1) == ' ') {
233 $link = ' '. $op;
234 }
235 if ($op == '@') {
236 if ($account->uid) {
237 $link .= theme('username', $account);
238 }
239 }
240 else if ($op == '#') {
241 if (!empty($term)) {
242 $dest = _facebook_status_tags_resolve($term);
243 if ($dest) {
244 $link .= l($term->name, $dest);
245 }
246 }
247 }
248 if (trim($link) == $op) {
249 $link = $match;
250 }
251 $links[] = $link;
252 }
253 return str_replace($matches[0], $links, $text);
254 }
255
256 /**
257 * Resolves the URL to which to redirect a taxonomy term.
258 *
259 * @param $term
260 * A taxonomy term object.
261 * @return
262 * The resolved URL.
263 */
264 function _facebook_status_tags_resolve($term) {
265 $url = variable_get('facebook_status_tags_url', 'statuses/term/[term-id]');
266 if (!trim($url)) {
267 return;
268 }
269 $phpversion = drupal_substr(phpversion(), 0, 1);
270 //str_ireplace() is not defined in PHP4 so we use the case-sensitive version.
271 if ($phpversion == 5) {
272 return str_ireplace(array('[term-id]', '[term-name]'), array($term->tid, $term->name), $url);
273 }
274 else {
275 return str_replace(array('[term-id]', '[term-name]'), array($term->tid, $term->name), $url);
276 }
277 }
278
279 /**
280 * Replaces both the username and hash tags.
281 */
282 function _facebook_status_tags_replace($text) {
283 $text = _facebook_status_tags_filter($text, '@');
284 $text = _facebook_status_tags_filter($text, '#');
285 return $text;
286 }
287
288 /**
289 * Gets a taxonomy term by name.
290 */
291 function _facebook_status_tags_get_term($name) {
292 return db_fetch_object(db_query("SELECT tid, name FROM {term_data} WHERE LOWER(name) = LOWER('%s') AND vid = %d", $name, variable_get('facebook_status_tags_vid', -1)));
293 }
294
295 //=================
296 //FBSS INTEGRATION.
297 //=================
298
299 /**
300 * Implementation of hook_facebook_status_render().
301 */
302 function facebook_status_tags_facebook_status_render($account, $status, $linked = TRUE) {
303 if ($linked) {
304 return array('_facebook_status_tags_replace' => array());
305 }
306 }
307
308 /**
309 * Implementation of hook_facebook_status_save().
310 */
311 function facebook_status_tags_facebook_status_save($account, $status, $sid) {
312 //Users.
313 $pattern = '/([\s]@.+\b)|(^@.+\b)/U';
314 preg_match_all($pattern, $status, $matches);
315 $matches = $matches[0];
316 $old_matches = array();
317 foreach ($matches as $match) {
318 $match = drupal_substr(trim($match), 1);
319 $account = user_load(array('name' => $match));
320 if ($account->uid) {
321 if (!in_array($match, $old_matches)) {
322 $array = array('sid' => $sid, 'rid' => $account->uid, 'type' => 'user');
323 drupal_write_record('facebook_status_tags', $array);
324 }
325 $old_matches[] = $match;
326 }
327 }
328
329 //Terms.
330 if (!module_exists('taxonomy') || variable_get('facebook_status_tags_vid', -1) == -1) {
331 return;
332 }
333 $pattern = '/([\s]#.+\b)|(^#.+\b)/U';
334 preg_match_all($pattern, $status, $matches);
335 $matches = $matches[0];
336 $old_matches = array();
337 foreach ($matches as $match) {
338 $match = drupal_substr(trim($match), 1);
339 //If the term does not exist, create it.
340 $term = _facebook_status_tags_get_term($match);
341 if (empty($term)) {
342 $term = array(
343 'vid' => variable_get('facebook_status_tags_vid', -1),
344 'name' => $match,
345 'description' => '',
346 'weight' => 0,
347 );
348 taxonomy_save_term($term);
349 }
350 if (!in_array($match, $old_matches)) {
351 $array = array('sid' => $sid, 'rid' => $term->tid, 'type' => 'term');
352 drupal_write_record('facebook_status_tags', $array);
353 }
354 $old_matches[] = $match;
355 }
356 }
357
358 /**
359 * Implementation of hook_facebook_status_delete().
360 */
361 function facebook_status_tags_facebook_status_delete($sid) {
362 db_query("DELETE FROM {facebook_status_tags} WHERE sid = %d", $sid);
363 }
364
365 //===================
366 //OTHER INTEGRATIONS.
367 //===================
368
369 /**
370 * Implementation of hook_views_api().
371 */
372 function facebook_status_tags_views_api() {
373 return array('api' => 2);
374 }
375
376 /**
377 * Implementation of hook_taxonomy().
378 */
379 function facebook_status_tags_taxonomy($op, $type, $array = NULL) {
380 if ($op != 'delete') {
381 return;
382 }
383 if ($type == 'term') {
384 db_query("DELETE FROM {facebook_status_tags} WHERE rid = %d AND type = 'term'", $array['tid']);
385 }
386 else if ($type == 'vocabulary') {
387 if ($array['vid'] === variable_get('facebook_status_tags_vid', -1)) {
388 //If the vocabulary is deleted, all the tags will no longer exist, so the references are invalid.
389 db_query("DELETE FROM {facebook_status_tags} WHERE type = 'term'");
390 variable_set('facebook_status_tags_vid', -1);
391 }
392 }
393 }

  ViewVC Help
Powered by ViewVC 1.1.2