/[drupal]/contributions/modules/bio/bio_views.inc
ViewVC logotype

Contents of /contributions/modules/bio/bio_views.inc

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


Revision 1.2 - (show annotations) (download) (as text)
Sat Apr 11 01:32:50 2009 UTC (7 months, 2 weeks ago) by vauxia
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +539 -0 lines
File MIME type: text/x-php
Adding bio_panels.inc and bio_views.inc from D5 branch
1 <?php
2 // $Id: bio_views.inc,v 1.1.2.7 2008/03/19 18:46:38 dww Exp $
3
4 /**
5 * @file
6 * Views integration for Bio module.
7 *
8 * The Bio module integrates with Views by re-exposing the Bio node for an
9 * author as part of any Views query.
10 *
11 * For example, it is possible to perform queries like:
12 * - Find all blog posts by authors who have Bio nodes tagged with the term
13 * "kayaking."
14 * - Find all the Bio nodes by authors who have a first name (where "first
15 * name" is a field) like "joe."
16 * - Find all the forum posts by the most popular authors, ranked by most
17 * viewed Bio pages.
18 *
19 * This file also provides two filters:
20 * - Node: Type is Bio node:
21 * This is useful for shipping premade views that rely on Bio, but are not
22 * tied to a particular type of node acting as the Bio node (e.g. on one site
23 * it might be "Biography," and on another "profile").
24 * - Bio: Author has Bio node:
25 * This is useful for only returning results where the author has created a
26 * Bio node. That way, if you are exposing Bio fields (e.g. the "interests"
27 * taxonomy), you can be sure that a Bio node exists for every other node
28 * returned in the query.
29 *
30 * See the README for more information on creating Views with Bio information.
31 */
32
33 /**
34 * Real implementation of hook_views_table_alter().
35 */
36 function _bio_views_tables_alter(&$tables) {
37 // Amass some data to use later.
38 $bio_type = bio_get_type();
39 $bio_name = node_get_types('name', $bio_type);
40
41 if (module_exists('taxonomy')) {
42 $vocabs = array_keys(taxonomy_get_vocabularies($bio_type));
43 }
44
45 // Fetch some CCK info if CCK is installed.
46 $bio_fields = array();
47 if (module_exists('content')) {
48 $content_type_info = content_types($bio_type);
49 if (is_array($content_type_info['fields'])) {
50 $bio_fields = array_keys($content_type_info['fields']);
51 }
52 }
53
54 // The first step is to copy the node table and alias it as the "node" table.
55 // This allows us to access all node table data. Later, we can point other
56 // modules at the "bio" table and it will behave just like the node table.
57 $old_node = $tables['node'];
58 // TODO: Not sure what this does, remove it.
59 unset($old_node['provider']);
60 $old_node['join'] = array(
61 // TODO: Default option is left. I think inner is probably better?
62 //'type' => 'inner',
63 'left' => array(
64 'table' => 'node',
65 'field' => 'uid'
66 ),
67 'right' => array(
68 'field' => 'uid'
69 ),
70 'extra' => array(
71 // TODO: Will I need to specify bio.type instead of type?
72 'type' => $bio_type,
73 ),
74 );
75
76 // Remove some fields, filters, and sorts that don't make sense for a joined
77 // Bio table.
78
79 // Node: Type.
80 unset($old_node['fields']['type']);
81 // Node: Type.
82 unset($old_node['filters']['type']);
83 // Node: Author is anonymous.
84 unset($old_node['filters']['anon']);
85 // Node: Author is current user.
86 unset($old_node['filters']['currentuid']);
87 // Node: Current user authored or commented.
88 unset($old_node['filters']['currentuidtouched']);
89 // Node: Type.
90 unset($old_node['sorts']['type']);
91 // Node: Random.
92 unset($old_node['sorts']['random']);
93
94 // For bio_node, nid is a real column.
95 unset($old_node['fields']['nid']['notafield']);
96
97 // Prefix descriptions with "Bio:" to differentiate them from standard stuff.
98 _bio_rename_table_labels($old_node, $bio_name);
99
100 // Save our worked up node table back in the array.
101 $tables['bio'] = $old_node;
102
103 // Bio copies all other tables and renames them bio_foo. This allows us to
104 // re-expose all the data of the Bio node in a forward compatible,
105 // transparent manner. We assume all tables connect to node (via
106 // intermediate tables). For now, a safe assumption.
107
108 // Without this copy, Apache would spin off and die a horrible death.
109 $table_copy = $tables;
110 foreach ($table_copy as $name => $data) {
111
112 // We can skip the node and bio tables. Other tables can be skipped, too.
113 // TODO: Is there a use case for including comments? Comment stats are
114 // pretty useful, but do we really need: "show me the comments on the
115 // profiles of authors who wrote a blog post about foo?"
116 if (in_array($name, array('node', 'bio', 'users', 'users_roles', 'comments', 'book', 'book_parent_node', 'temp_search_results'))) {
117 continue;
118 }
119
120 // skip anything that joins against UID, we don't need that (e.g. profile_xxx)
121 if ($data['join']['left']['table'] == 'node' && $data['join']['left']['field'] == 'uid') {
122 continue;
123 }
124
125 // we should skip tables that don't relate to bio node types specifically
126 // e.g. taxonomy vocabs that don't apply, cck fields that aren't in the bio node type, etc.
127
128 // Skip unneeded taxonomy vocabularies.
129 if (strpos($name, 'term_node_') === 0) {
130 $vid = substr($name, 10);
131 if (!in_array($vid, $vocabs)) {
132 continue;
133 }
134 }
135 // Skip fields not assigned to the Bio node type.
136 elseif (strpos($name, 'node_data_') === 0) {
137 $field = substr($name, 10);
138 if (!in_array($field, $bio_fields)) {
139 continue;
140 }
141 }
142
143 // If the table joins directly to node, make it's new join point "bio."
144 // If it joins against something else, assume that we'll create a "bio_X"
145 // for it at some point.
146 if ($data['join']['left']['table'] == 'node') {
147 $data['join']['left']['table'] = 'bio';
148 }
149 else {
150 $data['join']['left']['table'] = 'bio_'. $data['join']['left']['table'];
151 }
152 _bio_rename_table_labels($data, $bio_name);
153 $tables["bio_$name"] = $data;
154 }
155
156 // Now that all the bio_* tables are ready, add some other useful filters to
157 // the mix.
158
159 // Node: Type is Bio node -- cribbed from views_node.inc.
160 $tables['node']['filters']['biotype'] = array(
161 'field' => 'type',
162 'name' => t('Node: Type is Bio node'),
163 'operator' => array('=' => t('Is'), '!=' => t('Is not')),
164 'value' => _bio_provide_hidden_form($bio_type, $bio_name),
165 'help' => t('This allows you to filter by whether or not the node is a bio node. Select "Is" to limit to bio nodes, select "is not" to limit to all other content types'),
166 );
167
168 // Bio: Author has a Bio -- limits the results (e.g. blog posts) to those
169 // where the author has a Bio. Relies on http://drupal.org/node/142504.
170 $tables['bio']['filters']['author_has_bio'] = array(
171 'field' => 'uid',
172 'name' => t('Bio: Author has a Bio'),
173 'operator' => array('IS NOT' => t('Does'), 'IS' => t('Does not')),
174 'value' => _bio_provide_hidden_form(NULL, t('Have a bio node')),
175 'help' => t('Filter in only nodes for which the author has or does not have a bio node.'),
176 'handler' => 'views_handler_filter_null',
177 );
178
179 // Override the default handler on the "is new" filter, as it needs some very
180 // specific table names.
181 $tables['bio_history']['filters']['timestamp']['handler'] = 'bio_handler_filter_isnew';
182 }
183
184 /**
185 * Helper function to rename Node: Title => Bio: Node: Title, etc.
186 */
187 function _bio_rename_table_labels(&$table, $bio_name) {
188 foreach (array('fields', 'sorts', 'filters') as $section) {
189 if (is_array($table[$section])) {
190 foreach ($table[$section] as $id => $object) {
191 $table[$section][$id]['name'] = $bio_name .': '. $object['name'];
192 }
193 }
194 }
195 }
196
197 /**
198 * Used to force the value of certain form fields by converting to markup.
199 */
200 function _bio_provide_hidden_form($value, $markup) {
201 $form['text'] = array(
202 '#type' => 'markup',
203 '#value' => $markup,
204 );
205 $form['value'] = array(
206 '#type' => 'value',
207 '#value' => $value,
208 );
209
210 return $form;
211 }
212
213 /**
214 * Custom filter for new content. Copied directly from views_node.inc and modified to use bio_* tables.
215 */
216 function _bio_handler_filter_isnew($op, $filter, $filterinfo, &$query) {
217 global $user;
218 if (!$user || !$user->uid) {
219 return;
220 }
221
222 // Hey, Drupal kills old history, so nodes that haven't been updated
223 // since NODE_NEW_LIMIT are bzzzzzzzt outta here!
224
225 $limit = time() - NODE_NEW_LIMIT;
226
227 $query->ensure_table('bio_history');
228 if (module_exists('comment')) {
229 $query->ensure_table('bio_node_comment_statistics');
230 $clause = ("OR bio_node_comment_statistics.last_comment_timestamp > (***CURRENT_TIME*** - $limit)");
231 $clause2 = "OR bio_history.timestamp < bio_node_comment_statistics.last_comment_timestamp";
232 }
233
234 // NULL means a history record doesn't exist. That's clearly new content.
235 // Unless it's very very old content. Everything in the query is already
236 // type safe cause none of it is coming from outside here.
237 $query->add_where("(bio_history.timestamp IS NULL AND (bio.changed > (***CURRENT_TIME***-$limit) $clause)) OR bio_history.timestamp < bio.changed $clause2");
238 }
239
240 /**
241 * Real implementation of hook_views_query_alter().
242 *
243 * For any bio_* table, we need to make sure the bio_nid is added.
244 */
245 function _bio_views_query_alter(&$query, $view, $summary, $level) {
246 // See if we need to add the Bio module.
247 if (_bio_should_add_nid($query, $view)) {
248 $query->ensure_table('bio');
249 $query->add_field('nid', 'bio', 'bio_nid');
250 }
251 }
252
253 /**
254 * Helper function to determine if we need bio.nid in the query.
255 *
256 * @todo This looks like a bit of a hack. What happens if I install the biology
257 * module? :P
258 */
259 function _bio_should_add_nid($query, $view) {
260 foreach ($view->field as $field) {
261 if (strpos($field['tablename'], 'bio') === 0) {
262 return true;
263 }
264 }
265
266 foreach ($view->filter as $filter) {
267 if (strpos($filter['tablename'], 'bio') === 0) {
268 return true;
269 }
270 }
271
272 return false;
273 }
274
275 /**
276 * Real implemenation of hook_views_default_tables().
277 *
278 * Default views are:
279 * - recent_biographies:
280 * A listing of teasers of recent Bio nodes, regradless of what the Bio node
281 * type is.
282 * - author_tracker:
283 * Just like the usual tracker, but using Bio node titles instead of the user
284 * name for the "author" column.
285 *
286 * These Views are disabled by default.
287 */
288 function _bio_views_default_views() {
289 // A little set up to make these views look nicer :-)
290 $bio_type = bio_get_type();
291 $bio_name = node_get_types('name', $bio_type);
292
293 $view = new stdClass();
294 $view->disabled = true;
295 $view->name = 'recent_biographies';
296 $view->description = 'A list of recently created biographies, from the bio module. The url changes to whatever your bio node type is, as does the title.';
297 $view->access = array(
298 );
299 $view->view_args_php = '';
300 $view->page = TRUE;
301 $view->page_title = "Recent $bio_name Entries";
302 $view->page_header = '';
303 $view->page_header_format = '1';
304 $view->page_footer = '';
305 $view->page_footer_format = '1';
306 $view->page_empty = '';
307 $view->page_empty_format = '1';
308 $view->page_type = 'teaser';
309 $view->url = $bio_type;
310 $view->use_pager = TRUE;
311 $view->nodes_per_page = '10';
312 $view->sort = array(
313 array(
314 'tablename' => 'node',
315 'field' => 'created',
316 'sortorder' => 'DESC',
317 'options' => 'normal',
318 ),
319 );
320 $view->argument = array(
321 );
322 $view->field = array(
323 );
324 $view->filter = array(
325 array(
326 'tablename' => 'node',
327 'field' => 'biotype',
328 'operator' => '=',
329 'options' => '',
330 'value' => 'bio',
331 ),
332 );
333 $view->exposed_filter = array(
334 );
335 $view->requires = array(node);
336 $views[$view->name] = $view;
337
338 $view = new stdClass();
339 $view->disabled = true;
340 $view->name = 'tracker_bio';
341 $view->description = 'Shows all new activity on system using the bio node title as the author name.';
342 $view->access = array(
343 );
344 $view->view_args_php = '';
345 $view->page = TRUE;
346 $view->page_title = 'Recent posts';
347 $view->page_header = '';
348 $view->page_header_format = '1';
349 $view->page_footer = '';
350 $view->page_footer_format = '1';
351 $view->page_empty = '';
352 $view->page_empty_format = '1';
353 $view->page_type = 'table';
354 $view->url = 'tracker';
355 $view->use_pager = TRUE;
356 $view->nodes_per_page = '25';
357 $view->menu = TRUE;
358 $view->menu_title = 'Recent posts';
359 $view->menu_tab = FALSE;
360 $view->menu_tab_weight = '0';
361 $view->menu_tab_default = FALSE;
362 $view->menu_tab_default_parent = NULL;
363 $view->menu_parent_tab_weight = '0';
364 $view->menu_parent_title = '';
365 $view->sort = array(
366 array(
367 'tablename' => 'node_comment_statistics',
368 'field' => 'last_comment_timestamp',
369 'sortorder' => 'DESC',
370 'options' => 'normal',
371 ),
372 );
373 $view->argument = array(
374 array(
375 'type' => 'uid',
376 'argdefault' => '2',
377 'title' => 'recent posts for %1',
378 'options' => '',
379 'wildcard' => '',
380 'wildcard_substitution' => '',
381 ),
382 );
383 $view->field = array(
384 array(
385 'tablename' => 'node',
386 'field' => 'type',
387 'label' => 'Type',
388 ),
389 array(
390 'tablename' => 'node',
391 'field' => 'title',
392 'label' => 'Title',
393 'handler' => 'views_handler_field_nodelink_with_mark',
394 'options' => 'link',
395 ),
396 array(
397 'tablename' => 'bio',
398 'field' => 'title',
399 'label' => 'Author',
400 'handler' => 'views_handler_field_nodelink',
401 'options' => 'link',
402 ),
403 array(
404 'tablename' => 'node_comment_statistics',
405 'field' => 'comment_count',
406 'label' => 'Replies',
407 'handler' => 'views_handler_comments_with_new',
408 ),
409 array(
410 'tablename' => 'node_comment_statistics',
411 'field' => 'last_comment_timestamp',
412 'label' => 'Last Post',
413 'handler' => 'views_handler_field_since',
414 ),
415 );
416 $view->filter = array(
417 array(
418 'tablename' => 'node',
419 'field' => 'status',
420 'operator' => '=',
421 'options' => '',
422 'value' => '1',
423 ),
424 array(
425 'tablename' => 'node',
426 'field' => 'biotype',
427 'operator' => '!=',
428 'options' => '',
429 'value' => 'bio',
430 ),
431 );
432 $view->exposed_filter = array(
433 );
434 $view->requires = array(node_comment_statistics, node, bio);
435 $views[$view->name] = $view;
436
437 return $views;
438 }
439
440 /**
441 * Real implemenation of hook_views_tables().
442 *
443 * Exposes data from the {user} table, such as the full username, account
444 * status, e-mail address, etc, to views of the corresponding bio nodes.
445 */
446 function _bio_views_tables() {
447 $tables['bio'] = array(
448 'name' => 'bio',
449 'join' => array(
450 'type' => 'inner',
451 'left' => array(
452 'table' => 'node',
453 'field' => 'nid'
454 ),
455 'right' => array(
456 'field' => 'nid'
457 ),
458 ),
459 );
460 $tables['bio_users'] = array(
461 'name' => 'users',
462 'join' => array(
463 'type' => 'inner',
464 'left' => array(
465 'table' => 'bio',
466 'field' => 'uid'
467 ),
468 'right' => array(
469 'field' => 'uid'
470 ),
471 ),
472 'fields' => array(
473 'name' => array(
474 'name' => t('Bio: User: Username'),
475 'uid' => 'uid',
476 'addlfields' => array('uid'),
477 'sortable' => TRUE,
478 'help' => t('The username of the user associated with a given bio.'),
479 'handler' => 'views_handler_field_username',
480 ),
481 'mail' => array(
482 'name' => t('Bio: User: E-mail'),
483 'handler' => 'views_handler_field_email',
484 'help' => t('The e-mail address of the user associated with a given bio.'),
485 'sortable' => TRUE,
486 ),
487 'status' => array(
488 'name' => t('Bio: User: Account status'),
489 'help' => t('The account status of the user associated with a given bio.'),
490 'handler' => 'bio_views_handler_field_user_status',
491 'sortable' => TRUE,
492 ),
493 'picture' => array(
494 'name' => t('Bio: User: Picture'),
495 'field' => 'uid',
496 'help' => t('The picture of the user associated with a given bio.'),
497 'handler' => 'views_handler_field_userpic',
498 'sortable' => FALSE,
499 ),
500 'signature' => array(
501 'name' => t('Bio: User: Signature'),
502 'help' => t('The signature of the user associated with a given bio.'),
503 'sortable' => FALSE,
504 ),
505 'created' => array(
506 'name' => t('Bio: User: Created time'),
507 'help' => t("The creation time of the user associated with a given bio. The option field may be used to specify the custom date format as it's required by the date() function or if 'as time ago' has been chosen to customize the granularity of the time interval."),
508 'handler' => views_handler_field_dates(),
509 'option' => 'string',
510 'sortable' => TRUE,
511 ),
512 'access' => array(
513 'name' => t('Bio: User: Access time'),
514 'help' => t("The last access time of the user associated with a given bio. The option field may be used to specify the custom date format as it's required by the date() function or if 'as time ago' has been chosen to customize the granularity of the time interval."),
515 'handler' => views_handler_field_dates(),
516 'option' => 'string',
517 'sortable' => TRUE,
518 ),
519 'login' => array(
520 'name' => t('Bio: User: Login time'),
521 'help' => t("The last login time of the user associated with a given bio. The option field may be used to specify the custom date format as it's required by the date() function or if 'as time ago' has been chosen to customize the granularity of the time interval."),
522 'handler' => views_handler_field_dates(),
523 'option' => 'string',
524 'sortable' => TRUE,
525 ),
526 ),
527 );
528 return $tables;
529 }
530
531 function bio_views_handler_field_user_status($fieldinfo, $fielddata, $value, $data) {
532 return $value == 0 ? t('Blocked') : t('Active');
533 }
534
535 if (!function_exists('views_handler_field_email')) {
536 function views_handler_field_email($fieldinfo, $fielddata, $value, $data) {
537 return l($value, 'mailto:' . $value);
538 }
539 }

  ViewVC Help
Powered by ViewVC 1.1.2