Project

General

Profile

Paste
Download (5.76 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / flag / includes / views / flag_handler_field_ops.inc @ 4cfd8be6

1
<?php
2

    
3
/**
4
 * @file
5
 * Contains the flag Ops field handler.
6
 */
7

    
8
/**
9
 * Views field handler for the Flag operations links (flag/unflag).
10
 *
11
 * @ingroup views
12
 */
13
class flag_handler_field_ops extends views_handler_field {
14

    
15
  /**
16
   * Returns the flag object associated with our field.
17
   *
18
   * A field is in some relationship. This function reaches out for this
19
   * relationship and reads its 'flag' option, which holds the flag name.
20
   */
21
  function get_flag() {
22
    // When editing a view it's possible to delete the relationship (either by
23
    // error or to later recreate it), so we have to guard against a missing
24
    // one.
25
    if (isset($this->view->relationship[$this->options['relationship']])) {
26
      return $this->view->relationship[$this->options['relationship']]->get_flag();
27
    }
28
  }
29

    
30
  /**
31
   * Return the the relationship we're linked to. That is, the alias for its
32
   * table (which is suitbale for use with the various methods of the 'query'
33
   * object).
34
   */
35
  function get_parent_relationship() {
36
    $parent = $this->view->relationship[$this->options['relationship']]->options['relationship'];
37
    if (!$parent || $parent == 'none') {
38
      // Base query table.
39
      return NULL;
40
    }
41
    else {
42
      return $this->view->relationship[$parent]->alias;
43
    }
44
  }
45

    
46
  function option_definition() {
47
    $options = parent::option_definition();
48
    $options['link_type'] = array('default' => '');
49
    return $options;
50
  }
51

    
52
  function options_form(&$form, &$form_state) {
53
    parent::options_form($form, $form_state);
54

    
55
    $form['link_type'] = array(
56
      '#type' => 'radios',
57
      '#title' => t('Link type'),
58
      '#options' => array('' => t('Use flag link settings')) + _flag_link_type_options(),
59
      '#default_value' => $this->options['link_type'],
60
    );
61
  }
62

    
63
  /**
64
   * Override base ::query(). The purpose here is to make it possible for the
65
   * render() method to know two things: what's the content ID, and whether
66
   * it's flagged.
67
   */
68
  function query() {
69
    if (!($flag = $this->get_flag())) {
70
      // Error message is printed in render().
71
      return;
72
    }
73
    $info = $flag->get_views_info();
74
    $parent = $this->get_parent_relationship();
75

    
76
    // Find out if the content is flagged. We can't just peek at some field in
77
    // our loaded table because it doesn't always reflect the user browsing the
78
    // page. So we explicitly add the flagging table to find this out.
79
    // If the relationship is created with 'Current User' checked, we probably
80
    // already have the appropriate join. We just need the appropriate table
81
    // alias for that join. We look in the relationship settings to see if
82
    // user_scope is set to 'current' to determine this.
83
    $relationship = $this->view->relationship[$this->options['relationship']];
84
    if (isset($relationship->options['user_scope']) && $relationship->options['user_scope'] == 'current') {
85
      $table_alias = $relationship->alias;
86
    }
87
    // Otherwise, let's set up the alias, keeping it unique for this flag in
88
    // case there are multiple flag relationships in a single view.
89
    else {
90
      $table_alias = 'flagging_current_user_' . $flag->fid;
91
    }
92
    // Now that we have the table alias, let's see if it's already been joined
93
    // to. If it hasn't, we'll set up a join.
94
    if (!isset($this->query->table_queue[$table_alias])) {
95
      $join = new views_join();
96
      $join->construct('flagging', $info['views table'], $info['join field'], 'entity_id');
97
      $join->extra[] = array(
98
        'field' => 'fid',
99
        'value' => $flag->fid,
100
        'numeric' => TRUE,
101
      );
102
      if (!$flag->global) {
103
        $join->extra[] = array(
104
          'field' => 'uid',
105
          'value' => '***CURRENT_USER***',
106
          'numeric' => TRUE,
107
        );
108
        $join->extra[] = array(
109
          'field' => 'sid',
110
          'value' => '***FLAG_CURRENT_USER_SID***',
111
          'numeric' => TRUE,
112
        );
113
      }
114
      $table_alias = $this->query->add_table($table_alias, $parent, $join);
115
    }
116
    $this->aliases['is_flagged'] = $this->query->add_field($table_alias, 'entity_id');
117

    
118
    // Next, find out the content ID. We can't add_field() on this table
119
    // (flagging), because its entity_id may be NULL (in case no user has
120
    // flagged this content, and it's a LEFT JOIN). So we reach to the parent
121
    // relationship and add_field() *its* content ID column.
122
    $left_table = $this->view->relationship[$this->options['relationship']]->table_alias;
123
    $this->aliases['entity_id'] = $this->query->add_field($left_table, $info['join field']);
124
  }
125

    
126
  /**
127
   * Find out if the flag applies to each item seen on the page. It's done in a
128
   * separate DB query to to avoid complexity and to make 'many to one' tests
129
   * (e.g. checking user roles) possible without causing duplicate rows.
130
   */
131
  function pre_render(&$values) {
132
    if (!($flag = $this->get_flag())) {
133
      // Error message is printed in render().
134
      return;
135
    }
136

    
137
    $ids = array();
138
    foreach ($values as $row) {
139
      $entity_id = $row->{$this->aliases['entity_id']};
140
      $is_flagged = $row->{$this->aliases['is_flagged']};
141
      if (isset($entity_id)) {
142
        $ids[$entity_id] = $is_flagged ? 'unflag' : 'flag';
143
      }
144
    }
145
    $this->flag_applies = $ids ? $flag->access_multiple($ids) : array();
146
  }
147

    
148
  function render($values) {
149
    if (!($flag = $this->get_flag())) {
150
      // get_flag() itself will print a more detailed message.
151
      return t('Missing flag');
152
    }
153

    
154
    $entity_id = $values->{$this->aliases['entity_id']};
155
    $is_flagged = $values->{$this->aliases['is_flagged']};
156

    
157
    if (empty($this->flag_applies[$entity_id])) {
158
      // Flag does not apply to this content.
159
      return;
160
    }
161

    
162
    if (!empty($this->options['link_type'])) {
163
      $flag->link_type = $this->options['link_type'];
164
    }
165
    return $flag->theme($is_flagged ? 'unflag' : 'flag', $entity_id);
166
  }
167
}