Projet

Général

Profil

Paste
Télécharger (13,6 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ldap / ldap_views / plugins / ldap_views_plugin_query_ldap.inc @ bc175c27

1
<?php
2

    
3
/**
4
 * @file
5
 * Defines the default query object which builds and execute a ldap query
6
 */
7

    
8
class ldap_views_plugin_query_ldap extends views_plugin_query {
9

    
10
  /**
11
   * The base dn for the LDAP search
12
   */
13
  private $basedn = '';
14

    
15
  /**
16
   * A list of filters to apply to the LDAP search
17
   */
18
  private $filter = array();
19

    
20
  /**
21
   * Builds the necessary info to execute the query.
22
   */
23
  function build(&$view) {
24
    $view->init_pager($view);
25

    
26
    // Let the pager modify the query to add limits.
27
    $this->pager->query();
28
  }
29

    
30
  function add_field($table, $field, $alias = '', $params = array()) {
31
    // We check for this specifically because it gets a special alias.
32
    if ($table == $this->base_table && $field == $this->base_field && empty($alias)) {
33
      $alias = $this->base_field;
34
    }
35

    
36
    if (!$alias && $table) {
37
      $alias = $table . '_' . $field;
38
    }
39

    
40
    // Make sure an alias is assigned
41
    $alias = $alias ? $alias : $field;
42

    
43
    // PostgreSQL truncates aliases to 63 characters: http://drupal.org/node/571548
44

    
45
    // We limit the length of the original alias up to 60 characters
46
    // to get a unique alias later if its have duplicates
47
    $alias = drupal_substr($alias, 0, 60);
48

    
49
    // Create a field info array.
50
    $field_info = array(
51
      'field' => $field,
52
      'table' => $table,
53
      'alias' => $alias,
54
    ) + $params;
55

    
56
    // Test to see if the field is actually the same or not. Due to
57
    // differing parameters changing the aggregation function, we need
58
    // to do some automatic alias collision detection:
59
    $base = $alias;
60
    $counter = 0;
61
    while (!empty($this->fields[$alias]) && $this->fields[$alias] != $field_info) {
62
      $field_info['alias'] = $alias = $base . '_' . ++$counter;
63
    }
64

    
65
    if (empty($this->fields[$alias])) {
66
      $this->fields[$alias] = $field_info;
67
    }
68

    
69
    return $alias;
70
  }
71

    
72
  function add_orderby($table, $field, $order, $alias = '', $params = array()) {
73
    $this->orderby[] = array(
74
      'field' => $field,
75
      'direction' => drupal_strtoupper($order)
76
    );
77
  }
78

    
79
  function add_basedn($basedn) {
80
    $this->basedn = !empty($this->basedn) ? $this->basedn : $basedn;
81
  }
82

    
83
  function add_filter($filter) {
84
    if (empty($filter)) {
85
      return;
86
    }
87
    $this->filter[] = $filter;
88
  }
89

    
90
  /**
91
   * Add a simple WHERE clause to the query. The caller is responsible for
92
   * ensuring that all fields are fully qualified (TABLE.FIELD) and that
93
   * the table already exists in the query.
94
   *
95
   * @param $group
96
   *   The WHERE group to add these to; groups are used to create AND/OR
97
   *   sections. Groups cannot be nested. Use 0 as the default group.
98
   *   If the group does not yet exist it will be created as an AND group.
99
   * @param $field
100
   *   The name of the field to check.
101
   * @param $value
102
   *   The value to test the field against. In most cases, this is a scalar. For more
103
   *   complex options, it is an array. The meaning of each element in the array is
104
   *   dependent on the $operator.
105
   * @param $operator
106
   *   The comparison operator, such as =, <, or >=. It also accepts more complex
107
   *   options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is an array
108
   *   = otherwise. If $field is a string you have to use 'formula' here.
109
   *
110
   * @see QueryConditionInterface::condition()
111
   */
112
  function add_where($group, $field, $value = NULL, $operator = NULL) {
113
    // Ensure all variants of 0 are actually 0. Thus '', 0 and NULL are all
114
    // the default group.
115
    if (empty($group)) {
116
      $group = 0;
117
    }
118

    
119
    // Check for a group.
120
    if (!isset($this->where[$group])) {
121
      $this->set_where_group('AND', $group);
122
    }
123

    
124
    $this->where[$group]['conditions'][] = array(
125
      'field' => $field,
126
      'value' => $value,
127
      'operator' => ltrim($operator, '!'),
128
      'negate' => drupal_substr($operator, 0, 1) == '!',
129
    );
130
  }
131

    
132
  /**
133
   * Construct the filter
134
   *
135
   * @param $where
136
   *   'where' or 'having'.
137
   */
138
  function build_condition() {
139
    $operator = array('AND' => '&', 'OR' => '|');
140
    $main_group = '';
141
    if (!isset($this->where)) {
142
      $this->where = array(); // Initialize where clause if not set
143
    }
144
    foreach ($this->where as $group => $info) {
145
      if (!empty($info['conditions'])) {
146
        $sub_group = '';
147
        foreach ($info['conditions'] as $key => $clause) {
148
          $item       = '(' . $clause['field'] . $clause['operator'] . $clause['value'] . ')';
149
          $sub_group .= $clause['negate'] ? "(!$item)" : $item;
150
        }
151
        $main_group .= count($info['conditions']) <= 1 ? $sub_group : '(' . $operator[$info['type']] . $sub_group . ')';
152
      }
153
    }
154
    return count($this->where) <= 1 ? $main_group : '(' . $operator[$this->group_operator] . $main_group . ')';
155
  }
156

    
157
  function build_ldap_basedn($basedn) {
158
    return !empty($this->basedn) ? array($this->basedn) : $basedn;
159
  }
160

    
161
  function build_contextual_filter() {
162
    $contextual_filter = '';
163
    foreach ($this->filter as $condition) {
164
      $contextual_filter .= drupal_substr($condition, 0, 1) != '(' ? "($condition)" : $condition;
165
    }
166
    return $contextual_filter;
167
  }
168

    
169
  function build_ldap_filter($filter) {
170
    $condition     = $this->build_condition();
171
    $contextual    = $this->build_contextual_filter();
172
    $search_filter = !empty($contextual) && !empty($condition) ? '(&' . $condition . $contextual . ')' : $condition . $contextual;
173
    return !empty($search_filter) ? $search_filter : $filter;
174
  }
175

    
176
  /**
177
   * Ensure a table exists in the queue; if it already exists it won't
178
   * do anything, but if it doesn't it will add the table queue. It will ensure
179
   * a path leads back to the relationship table.
180
   *
181
   * @param $table
182
   *   The unaliased name of the table to ensure.
183
   * @param $relationship
184
   *   The relationship to ensure the table links to. Each relationship will
185
   *   get a unique instance of the table being added. If not specified,
186
   *   will be the primary table.
187
   * @param $join
188
   *   A views_join object (or derived object) to join the alias in.
189
   *
190
   * @return
191
   *   The alias used to refer to this specific table, or NULL if the table
192
   *   cannot be ensured.
193
   */
194
  function ensure_table($table, $relationship = NULL, $join = NULL) {
195
    return $table;
196
  }
197

    
198
  /**
199
   * Executes the query and fills the associated view object with according
200
   * values.
201
   *
202
   * Values to set: $view->result, $view->total_rows, $view->execute_time,
203
   * $view->pager['current_page'].
204
   *
205
   * $view->result should contain an array of objects.
206
   */
207
  function execute(&$view) {
208
    $start       = microtime(TRUE);
209
    $entries     = array();
210
    $num_entries = 0;
211

    
212
    if (empty($this->options['qid'])) {
213
      watchdog('ldap_views', 'Query definition is empty');
214
      return;
215
    }
216
    foreach ($this->fields as $field) {
217
      $attributes[$field['alias']] = $field['field'];
218
      $field_alias[$field['alias']] = drupal_strtolower($field['field']);
219
    }
220

    
221
    $ldap_data   = new LdapQuery(ldap_views_get_qid($view));
222
    $ldap_server = new LdapServer($ldap_data->sid);
223
    $ldap_server->connect();
224
    $ldap_server->bind();
225
    // TODO: Can't use sizelimit if it must be ordered || cache?
226
    // $ldap_server->search() hasn't orderby (ldap_sort)
227
    // But we can't use ldap_sort because there's no DESC option
228
    foreach ($this->build_ldap_basedn($ldap_data->baseDn) as $basedn) {
229

    
230
      $result = $ldap_server->search($basedn, $this->build_ldap_filter($ldap_data->filter), array_values($attributes), 0, $ldap_data->sizelimit, $ldap_data->timelimit, $ldap_data->deref, $ldap_data->scope);
231
/**
232
    // ldap_sort can't be used because there's no DESC option
233
    if (!empty($this->orderby)) {
234
      // Array reverse, because the most specific are first - PHP works the opposite way of SQL.
235
      foreach (array_reverse($this->orderby) as $field) {
236
        @ldap_sort($ldap_server->connection, $result, $field['field']);
237
      }
238
    }
239
 */
240
    if ($result !== FALSE) { // not an error
241
        $entries = array_merge($entries, $result);
242
        $num_entries += $result['count'];
243
        unset($result['count']);
244
      }
245
    }
246
    if (property_exists($view->query, 'limit')) {
247
      $limit     = $view->query->limit;
248
    }
249
    $offset = property_exists($view->query, 'offset') ? $view->query->offset : 0;
250
    $result      = array();
251
    $sort_fields = array();
252
    if (!empty($this->orderby)) {
253
      foreach ($this->orderby as $orderby) {
254
        $sort_fields[drupal_strtolower($orderby['field'])]['direction'] = $orderby['direction'];
255
        $sort_fields[drupal_strtolower($orderby['field'])]['data']      = array();
256
      }
257

    
258
    }
259

    
260
    foreach ($entries as $key => &$entry) {
261
      if (isset($entry['jpegphoto'])) {
262
        $entry['jpegphoto'][0] = '<img src="data:image/jpeg;base64,' . base64_encode($entry['jpegphoto'][0]) . '" alt="photo" />';
263
      }
264
      if (isset($entry['thumbnailphoto'])) {
265
        $entry['thumbnailphoto'][0] = '<img src="data:image/jpeg;base64,' . base64_encode($entry['thumbnailphoto'][0]) . '" alt="photo" />';
266
      }
267
      foreach ($view->field as $field) {
268
        if (! isset($field_alias[$field->field_alias])) {
269
          continue;
270
        }
271
        $alias = $field_alias[$field->field_alias];
272
        if (is_array($entry) && array_key_exists($alias, $entry)) {
273
          if (is_array($entry[$alias])) {
274
            switch ($field->options['multivalue']) {
275
              case 'v-all':
276
                // remove 'count' index
277
                unset($entry[$alias]['count']);
278
                $entry[$alias] = implode($field->options['value_separator'], $entry[$alias]);
279
                break;
280
              case 'v-count':
281
                $entry[$alias] = $entry[$alias]['count'];
282
                break;
283
              case 'v-index':
284
                $index = $field->options['index_value'] >= 0 ? intval($field->options['index_value']) : $entry[$alias]['count'] + $field->options['index_value'];
285
                $entry[$alias] = array_key_exists($index, $entry[$alias]) ? $entry[$alias][$index] :
286
                                                                            $entry[$alias][0];
287
                break;
288
            }
289
          }
290
          // order criteria
291
          //If the field with alias $alias has a corresponding entry in $sort_fields, copy its value into the data key of $sort_fields for later sorting.
292
          if (array_key_exists($alias, $sort_fields)) {
293
            $sort_fields[$alias]['data'][$key] = $entry[$alias];
294
          }
295
        }
296
      }
297
    }
298
    if (!empty($this->orderby) && !empty($entries)) {
299
      $params = array();
300
      // In PHP 5.3 every parameter in the array has to be a reference when calling array_multisort() with call_user_func_array().
301
      $asc  = SORT_ASC;
302
      $desc = SORT_DESC;
303
      foreach ($sort_fields as &$field) {
304
        $params[] = &$field['data'];
305
        if (drupal_strtoupper($field['direction']) == 'ASC') {
306
          $params[] = &$asc;
307
        }
308
        else {
309
          $params[] = &$desc;
310
        }
311
      }
312
      $params[] = &$entries;
313

    
314
      // Some LDAP setups output a 'count' variable in the array, which changes the array size;
315
      // temporarily remove it, sort the arrays, and then put it back.
316
      if (array_key_exists('count', $entries)) {
317
        $countValue = $entries['count']; // remove the count variable
318
        unset($entries['count']);
319
        $params[] = &$entries;
320
        call_user_func_array('array_multisort', $params);
321
        $params['count'] = $countValue;
322
      }
323
      else {
324
        $params[] = &$entries;
325
        call_user_func_array('array_multisort', $params);
326
      }
327
    }
328

    
329
    for ($i = 0; (!isset($limit) || $i < $limit) && $offset + $i < $num_entries; $i++) {
330
      $row = array();
331
      $entry = &$entries[$offset + $i];
332
      foreach ($view->field as $field) {
333
        if (! isset($field_alias[$field->field_alias])) {
334
          continue;
335
        }
336
        if (array_key_exists($field_alias[$field->field_alias], $entry)) {
337
          $row[$field->field_alias] = $entry[$field_alias[$field->field_alias]];
338
        }
339
      }
340
      $result[] = $row;
341
    }
342

    
343
    $view->result       = $result;
344
    $view->total_rows   = $num_entries;
345
    $view->execute_time = microtime(TRUE) - $start;
346
    $view->query->pager->total_items  = $num_entries;
347
    $view->query->pager->update_page_info();
348

    
349
  }
350

    
351
  function option_definition() {
352
    $options = parent::option_definition();
353
    $options['qid'] = array('default' => '');
354

    
355
    return $options;
356
  }
357

    
358
  function options_form(&$form, &$form_state) {
359
/**
360
    $ldap_data = entity_load('ldap_data', FALSE);
361
    $options   = array();
362
    foreach ($ldap_data as $data) {
363
        $options[$data->qid] = $data->name;
364
    }
365
 */
366
    $queries = array();
367
    $queries['all'] = LdapQueryAdmin::getLdapQueryObjects();
368

    
369
  foreach ($queries['all'] as $_sid => $ldap_query) {
370
    if ($ldap_query->status == 1) {
371
      //$queries['enabled'][$_qid] = $ldap_query;
372
      $options[$ldap_query->qid] = $ldap_query->name;
373
    }
374
  }
375
// ******************************************************
376
      $form['qid'] = array(
377
      '#type' => 'select',
378
      '#title' => t('LDAP Search'),
379
      '#options' => $options,
380
      '#default_value' => $this->options['qid'],
381
      '#description' => t("The LDAP server to query."),
382
    );
383
  }
384

    
385

    
386
  /**
387
   * Let modules modify the query just prior to finalizing it.
388
   */
389
  function alter(&$view) {
390
    foreach (module_implements('views_query_alter') as $module) {
391
      $function = $module . '_views_query_alter';
392
      $function($view, $this);
393
    }
394
  }
395

    
396
/* Only when adding dynamic fields in ldap_views_views_data_alter()
397
  function options_submit(&$form, &$form_state) {
398
    parent::options_submit(&$form, &$form_state);
399
    if ($form_state['values']['query']['options']['qid'] != $form_state['view']->query->options['qid']) {
400
      views_invalidate_cache();
401
    }
402
  }
403
 */
404
}