~ubuntu-branches/debian/sid/php-horde-turba/sid

« back to all changes in this revision

Viewing changes to turba-4.1.0/lib/Driver/Sql.php

  • Committer: Package Import Robot
  • Author(s): Mathieu Parent
  • Date: 2013-08-11 13:16:25 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130811131625-z91stjvq51jr9onv
Tags: 4.1.1-1
New upstream version 4.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/**
3
 
 * Turba directory driver implementation for the Horde_Db database abstraction
4
 
 * layer.
5
 
 *
6
 
 * Copyright 2010-2013 Horde LLC (http://www.horde.org/)
7
 
 *
8
 
 * See the enclosed file LICENSE for license information (ASL).  If you did
9
 
 * did not receive this file, see http://www.horde.org/licenses/apache.
10
 
 *
11
 
 * @author   Jon Parise <jon@csh.rit.edu>
12
 
 * @author   Michael J. Rubinsky <mrubinsk@horde.org>
13
 
 * @category Horde
14
 
 * @license  http://www.horde.org/licenses/apache ASL
15
 
 * @package  Turba
16
 
 */
17
 
class Turba_Driver_Sql extends Turba_Driver
18
 
{
19
 
    /**
20
 
     * What can this backend do?
21
 
     *
22
 
     * @var array
23
 
     */
24
 
    protected $_capabilities = array(
25
 
        'delete_addressbook' => true,
26
 
        'delete_all' => true
27
 
    );
28
 
 
29
 
    /**
30
 
     * count() cache.
31
 
     *
32
 
     * @var array
33
 
     */
34
 
    protected $_countCache = array();
35
 
 
36
 
    /**
37
 
     * Handle for the current database connection.
38
 
     *
39
 
     * @var Horde_Db_Adapter
40
 
     */
41
 
    protected $_db;
42
 
 
43
 
    /**
44
 
     * Constructor.
45
 
     *
46
 
     * @param string $name   The source name
47
 
     * @param array $params  Additional parameters needed:
48
 
     * <pre>
49
 
     * 'db' - (Horde_Db_Adapter) A DB Adapter object.
50
 
     * </pre>
51
 
     */
52
 
    public function __construct($name = '', array $params = array())
53
 
    {
54
 
        if (empty($params['db'])) {
55
 
            throw new InvalidArgumentException('Missing required Horde_Db_Adapter object');
56
 
        }
57
 
        $this->_db = $params['db'];
58
 
        unset($params['db']);
59
 
 
60
 
        parent::__construct($name, $params);
61
 
    }
62
 
 
63
 
    /**
64
 
     * Returns the number of contacts of the current user in this address book.
65
 
     *
66
 
     * @return integer  The number of contacts that the user owns.
67
 
     */
68
 
    public function count()
69
 
    {
70
 
        $test = $this->getContactOwner();
71
 
        if (!isset($this->_countCache[$test])) {
72
 
            /* Build up the full query. */
73
 
            $query = 'SELECT COUNT(*) FROM ' . $this->_params['table'] .
74
 
                     ' WHERE ' . $this->toDriver('__owner') . ' = ?';
75
 
            $values = array($test);
76
 
 
77
 
            /* Run query. */
78
 
            try {
79
 
                $this->_countCache[$test] = $this->_db->selectValue($query, $values);
80
 
            } catch (Horde_Db_Exception $e) {
81
 
                $this->_countCache[$test] = 0;
82
 
            }
83
 
        }
84
 
 
85
 
        return $this->_countCache[$test];
86
 
    }
87
 
 
88
 
    /**
89
 
     * Searches the SQL database with the given criteria and returns a
90
 
     * filtered list of results. If the criteria parameter is an empty array,
91
 
     * all records will be returned.
92
 
     *
93
 
     * @param array $criteria       Array containing the search criteria.
94
 
     * @param array $fields         List of fields to return.
95
 
     * @param array $blobFields     TODO
96
 
     * @param boolean $count_only   Only return the count of matching entries,
97
 
     *                              not the entries themselves.
98
 
     *
99
 
     * @return array  Hash containing the search results.
100
 
     * @throws Turba_Exception
101
 
     */
102
 
    protected function _search(array $criteria, array $fields, array $blobFields = array(), $count_only = false)
103
 
    {
104
 
        return $this->_internalSearch($criteria, $fields, $blobFields, array(), $count_only);
105
 
    }
106
 
 
107
 
    /**
108
 
     * Searches the SQL database with the given criteria and returns a
109
 
     * filtered list of results. If the criteria parameter is an empty array,
110
 
     * all records will be returned.
111
 
     *
112
 
     * @param array $criteria        Array containing the search criteria.
113
 
     * @param array $fields          List of fields to return.
114
 
     * @param array $blobFields      TODO
115
 
     * @param array $appendWhere     An additional where clause to append.
116
 
     *                               Array should contain 'sql' and 'params'
117
 
     *                               params are used as bind parameters.
118
 
     * @param boolean $count_only   Only return the count of matching entries,
119
 
     *                              not the entries themselves.
120
 
     *
121
 
     * @return mixed array|integer  Hash containing the search results or the
122
 
     *                              count of matching entries.
123
 
     * @throws Turba_Exception
124
 
     */
125
 
    protected function _internalSearch(array $criteria, array $fields, $blobFields = array(), $appendWhere = array(), $count_only = false)
126
 
    {
127
 
        /* Build the WHERE clause. */
128
 
        $where = '';
129
 
        $values = array();
130
 
 
131
 
        if (count($criteria) || !empty($this->_params['filter'])) {
132
 
            foreach ($criteria as $key => $vals) {
133
 
                if ($key == 'OR' || $key == 'AND') {
134
 
                    if (!empty($where)) {
135
 
                        $where .= ' ' . $key . ' ';
136
 
                    }
137
 
                    $binds = $this->_buildSearchQuery($key, $vals);
138
 
                    $where .= '(' . $binds[0] . ')';
139
 
                    $values += $binds[1];
140
 
                }
141
 
            }
142
 
            $where = ' WHERE ' . $where;
143
 
            if (count($criteria) && !empty($this->_params['filter'])) {
144
 
                $where .= ' AND ';
145
 
            }
146
 
            if (!empty($this->_params['filter'])) {
147
 
                $where .= $this->_params['filter'];
148
 
            }
149
 
            if (count($appendWhere)) {
150
 
                $where .= ' AND ' . $appendWhere['sql'];
151
 
                $values = array_merge($values, $appendWhere['params']);
152
 
            }
153
 
        } elseif (count($appendWhere)) {
154
 
            $where = ' WHERE ' . $appendWhere['sql'];
155
 
            $values = array_merge($values, $appendWhere['params']);
156
 
        }
157
 
 
158
 
        /* Build up the full query. */
159
 
        if ($count_only) {
160
 
            $query = 'SELECT COUNT(*) FROM ' . $this->_params['table'] . $where;
161
 
            try {
162
 
                return $this->_db->selectValue($query, $values);
163
 
            } catch (Horde_Db_Exception $e) {
164
 
                throw new Turba_Exception($e);
165
 
            }
166
 
        } else {
167
 
            $query = 'SELECT ' . implode(', ', $fields) . ' FROM ' . $this->_params['table'] . $where;
168
 
            try {
169
 
               return $this->_parseRead($blobFields, $this->_db->selectAll($query, $values));
170
 
            } catch (Horde_Db_Exception $e) {
171
 
                throw new Turba_Exception($e);
172
 
            }
173
 
        }
174
 
    }
175
 
 
176
 
    protected function _parseRead($blobFields, $result)
177
 
    {
178
 
        $results = array();
179
 
        $columns = $this->_db->columns($this->_params['table']);
180
 
 
181
 
        foreach ($result as $row) {
182
 
            $entry = array();
183
 
 
184
 
            foreach ($row as $field => $val) {
185
 
                if (isset($blobFields[$field])) {
186
 
                    $entry[$field] = $columns[$field]->binaryToString($val);
187
 
                } else {
188
 
                    $entry[$field] = $this->_convertFromDriver($val);
189
 
                }
190
 
            }
191
 
 
192
 
            $results[] = $entry;
193
 
        }
194
 
 
195
 
        return $results;
196
 
    }
197
 
 
198
 
    /**
199
 
     * Prepares field lists for searchDuplicates().
200
 
     *
201
 
     * @param array $array  A list of field names.
202
 
     *
203
 
     * @return array  A prepared list of field names.
204
 
     */
205
 
    protected function _buildFields($array)
206
 
    {
207
 
        foreach ($array as &$entry) {
208
 
            $entry = is_array($entry)
209
 
                ? implode(',', $this->_buildFields($entry))
210
 
                : 'a1.' . $entry;
211
 
        }
212
 
 
213
 
        return $array;
214
 
    }
215
 
 
216
 
    /**
217
 
     * Builds the WHERE conditions for searchDuplicates().
218
 
     *
219
 
     * @param array $array  A list of field names.
220
 
     *
221
 
     * @return array  A list of WHERE conditions.
222
 
     */
223
 
    protected function _buildWhere($array)
224
 
    {
225
 
        foreach ($array as &$entry) {
226
 
            if (is_array($entry)) {
227
 
                $entry = reset($entry);
228
 
            }
229
 
            $entry = 'a1.' . $entry . ' IS NOT NULL AND a1.' . $entry . ' <> \'\'';
230
 
        }
231
 
 
232
 
        return $array;
233
 
    }
234
 
 
235
 
    /**
236
 
     * Builds the JOIN conditions for searchDuplicates().
237
 
     *
238
 
     * @param array $array  A list of field names.
239
 
     *
240
 
     * @return array  A list of JOIN conditions.
241
 
     */
242
 
    protected function _buildJoin($array)
243
 
    {
244
 
        foreach ($array as &$entry) {
245
 
            $entry = is_array($entry)
246
 
                ? implode(' AND ', $this->_buildJoin($entry))
247
 
                : 'a1.' . $entry . ' = a2.' . $entry;
248
 
        }
249
 
 
250
 
        return $array;
251
 
    }
252
 
 
253
 
    /**
254
 
     * Searches the current address book for duplicate entries.
255
 
     *
256
 
     * Duplicates are determined by comparing email and name or last name and
257
 
     * first name values.
258
 
     *
259
 
     * @return array  A hash with the following format:
260
 
     *                <code>
261
 
     *                array('name' => array('John Doe' => Turba_List, ...), ...)
262
 
     *                </code>
263
 
     * @throws Turba_Exception
264
 
     */
265
 
    public function searchDuplicates()
266
 
    {
267
 
        $owner = $this->getContactOwner();
268
 
        $fields = array();
269
 
        if (is_array($this->map['name'])) {
270
 
            if (in_array('lastname', $this->map['name']['fields']) &&
271
 
                isset($this->map['lastname'])) {
272
 
                $field = array($this->map['lastname']);
273
 
                if (in_array('firstname', $this->map['name']['fields']) &&
274
 
                    isset($this->map['firstname'])) {
275
 
                    $field[] = $this->map['firstname'];
276
 
                }
277
 
                $fields[] = $field;
278
 
            }
279
 
        } else {
280
 
            $fields[] = $this->map['name'];
281
 
        }
282
 
        if (isset($this->map['email'])) {
283
 
            $fields[] = $this->map['email'];
284
 
        }
285
 
        $nameFormat = $GLOBALS['prefs']->getValue('name_format');;
286
 
        if ($nameFormat != 'first_last' && $nameFormat != 'last_first') {
287
 
            $nameFormat = 'first_last';
288
 
        }
289
 
 
290
 
        $order = $this->_buildFields($fields);
291
 
        $joins = $this->_buildJoin($fields);
292
 
        $where = $this->_buildWhere($fields);
293
 
 
294
 
        $duplicates = array();
295
 
        for ($i = 0; $i < count($joins); $i++) {
296
 
            /* Build up the full query. */
297
 
            $query = sprintf('SELECT DISTINCT a1.%s,%s FROM %s a1 JOIN %s a2 ON %s AND a1.%s <> a2.%s WHERE a1.%s = ? AND a2.%s = ? AND %s ORDER BY %s',
298
 
                             $this->map['__key'],
299
 
                             $order[$i],
300
 
                             $this->_params['table'],
301
 
                             $this->_params['table'],
302
 
                             $joins[$i],
303
 
                             $this->map['__key'],
304
 
                             $this->map['__key'],
305
 
                             $this->map['__owner'],
306
 
                             $this->map['__owner'],
307
 
                             $where[$i],
308
 
                             $order[$i]);
309
 
 
310
 
            /* Run query. */
311
 
            try {
312
 
                $ids = $this->_db->selectValues($query, array($owner, $owner));
313
 
            } catch (Horde_Db_Exception $e) {
314
 
                throw new Turba_Exception($e);
315
 
            }
316
 
 
317
 
            $field = ($i == 0)
318
 
                ? 'name'
319
 
                : array_search($fields[$i], $this->map);
320
 
 
321
 
            $contacts = array();
322
 
            foreach ($ids as $id) {
323
 
                $contact = $this->getObject($id);
324
 
                $value = $contact->getValue($field);
325
 
                if ($field == 'name') {
326
 
                    $value = Turba::formatName($contact, $nameFormat);
327
 
                }
328
 
                /* HACK! */
329
 
                if ($field == 'email') {
330
 
                    $value = Horde_String::lower($value);
331
 
                }
332
 
                if (!isset($contacts[$value])) {
333
 
                    $contacts[$value] = new Turba_List();
334
 
                }
335
 
                $contacts[$value]->insert($contact);
336
 
            }
337
 
            if ($contacts) {
338
 
                $duplicates[$field] = $contacts;
339
 
            }
340
 
        }
341
 
 
342
 
        return $duplicates;
343
 
    }
344
 
 
345
 
    /**
346
 
     * Reads the given data from the SQL database and returns the results.
347
 
     *
348
 
     * @param string $key        The primary key field to use.
349
 
     * @param mixed $ids         The ids of the contacts to load.
350
 
     * @param string $owner      Only return contacts owned by this user.
351
 
     * @param array $fields      List of fields to return.
352
 
     * @param array $blobFields  Array of fields containing binary data.
353
 
     *
354
 
     * @return array  Hash containing the search results.
355
 
     * @throws Turba_Exception
356
 
     */
357
 
    protected function _read($key, $ids, $owner, array $fields,
358
 
                             array $blobFields = array())
359
 
    {
360
 
        $values = array();
361
 
 
362
 
        $in = '';
363
 
        if (is_array($ids)) {
364
 
            if (!count($ids)) {
365
 
                return array();
366
 
            }
367
 
 
368
 
            foreach ($ids as $id) {
369
 
                $in .= empty($in) ? '?' : ', ?';
370
 
                $values[] = $this->_convertToDriver($id);
371
 
            }
372
 
            $where = $key . ' IN (' . $in . ')';
373
 
        } else {
374
 
            $where = $key . ' = ?';
375
 
            $values[] = $this->_convertToDriver($ids);
376
 
        }
377
 
        if (isset($this->map['__owner'])) {
378
 
            $where .= ' AND ' . $this->map['__owner'] . ' = ?';
379
 
            $values[] = $this->_convertToDriver($owner);
380
 
        }
381
 
        if (!empty($this->_params['filter'])) {
382
 
            $where .= ' AND ' . $this->_params['filter'];
383
 
        }
384
 
 
385
 
        $query  = 'SELECT ' . implode(', ', $fields) . ' FROM '
386
 
            . $this->_params['table'] . ' WHERE ' . $where;
387
 
 
388
 
        try {
389
 
            return $this->_parseRead($blobFields, $this->_db->selectAll($query, $values));
390
 
        } catch (Horde_Db_Exception $e) {
391
 
            throw new Turba_Exception($e);
392
 
        }
393
 
    }
394
 
 
395
 
    /**
396
 
     * Adds the specified object to the SQL database.
397
 
     *
398
 
     * TODO
399
 
     *
400
 
     * @throws Turba_Exception
401
 
     */
402
 
    protected function _add(array $attributes, array $blob_fields = array())
403
 
    {
404
 
        list($fields, $values) = $this->_prepareWrite($attributes, $blob_fields);
405
 
        $query  = 'INSERT INTO ' . $this->_params['table']
406
 
            . ' (' . implode(', ', $fields) . ')'
407
 
            . ' VALUES (' . str_repeat('?, ', count($values) - 1) . '?)';
408
 
 
409
 
        try {
410
 
            $this->_db->insert($query, $values);
411
 
        } catch (Horde_Db_Exception $e) {
412
 
            throw new Turba_Exception($e);
413
 
        }
414
 
    }
415
 
 
416
 
    protected function _prepareWrite($attributes, $blob_fields)
417
 
    {
418
 
        $fields = $values = array();
419
 
 
420
 
        foreach ($attributes as $field => $value) {
421
 
            $fields[] = $field;
422
 
 
423
 
            if (!empty($value) && isset($blob_fields[$field])) {
424
 
                $values[] = new Horde_Db_Value_Binary($value);
425
 
            } else {
426
 
                $values[] = $this->_convertToDriver($value);
427
 
            }
428
 
        }
429
 
 
430
 
        return array($fields, $values);
431
 
    }
432
 
 
433
 
    /**
434
 
     * TODO
435
 
     */
436
 
    protected function _canAdd()
437
 
    {
438
 
        return true;
439
 
    }
440
 
 
441
 
    /**
442
 
     * Deletes the specified object from the SQL database.
443
 
     *
444
 
     * @throws Turba_Exception
445
 
     */
446
 
    protected function _delete($object_key, $object_id)
447
 
    {
448
 
        $query = 'DELETE FROM ' . $this->_params['table'] .
449
 
                 ' WHERE ' . $object_key . ' = ?';
450
 
        $values = array($object_id);
451
 
 
452
 
        try {
453
 
            $this->_db->delete($query, $values);
454
 
        } catch (Horde_Db_Exception $e) {
455
 
            throw new Turba_Exception($e);
456
 
        }
457
 
    }
458
 
 
459
 
    /**
460
 
     * Deletes all contacts from a specific address book.
461
 
     *
462
 
     * @param string $sourceName  The source to remove all contacts from.
463
 
     *
464
 
     * @return array  An array of UIDs
465
 
     * @throws Turba_Exception
466
 
     */
467
 
    protected function _deleteAll($sourceName = null)
468
 
    {
469
 
        if (!$GLOBALS['registry']->getAuth()) {
470
 
            throw new Turba_Exception('Permission denied');
471
 
        }
472
 
 
473
 
        /* Get owner id */
474
 
        $values = empty($sourceName)
475
 
            ? array($GLOBALS['registry']->getAuth())
476
 
            : array($sourceName);
477
 
 
478
 
        /* Need a list of UIDs so we can notify History */
479
 
        $query = 'SELECT '. $this->map['__uid'] . ' FROM '
480
 
            . $this->_params['table'] . ' WHERE owner_id = ?';
481
 
 
482
 
        try {
483
 
            $ids = $this->_db->selectValues($query, $values);
484
 
        } catch (Horde_Db_Exception $e) {
485
 
            throw new Turba_Exception($e);
486
 
        }
487
 
 
488
 
        /* Do the deletion */
489
 
        $query = 'DELETE FROM ' . $this->_params['table'] . ' WHERE owner_id = ?';
490
 
 
491
 
        try {
492
 
            $this->_db->delete($query, $values);
493
 
        } catch (Horde_Db_Exception $e) {
494
 
            throw new Turba_Exception($e);
495
 
        }
496
 
 
497
 
        return $ids;
498
 
    }
499
 
 
500
 
    /**
501
 
     * Saves the specified object in the SQL database.
502
 
     *
503
 
     * @param Turba_Object $object  The object to save.
504
 
     *
505
 
     * @return string  The object id, possibly updated.
506
 
     * @throws Turba_Exception
507
 
     */
508
 
    function _save(Turba_Object $object)
509
 
    {
510
 
        list($object_key, $object_id) = each($this->toDriverKeys(array('__key' => $object->getValue('__key'))));
511
 
        $attributes = $this->toDriverKeys($object->getAttributes());
512
 
        $blob_fields = $this->toDriverKeys($this->getBlobs());
513
 
 
514
 
        $where = $object_key . ' = ?';
515
 
        unset($attributes[$object_key]);
516
 
 
517
 
        list($fields, $values) = $this->_prepareWrite($attributes, $blob_fields);
518
 
 
519
 
        $values[] = $object_id;
520
 
 
521
 
        $query = 'UPDATE ' . $this->_params['table'] . ' SET ' . implode(' = ?, ', $fields) . ' = ? WHERE ' . $where;
522
 
 
523
 
        try {
524
 
            $this->_db->update($query, $values);
525
 
        } catch (Horde_Db_Exception $e) {
526
 
            throw new Turba_Exception($e);
527
 
        }
528
 
 
529
 
        return $object_id;
530
 
    }
531
 
 
532
 
    /**
533
 
     * Creates an object key for a new object.
534
 
     *
535
 
     * @param array $attributes  The attributes (in driver keys) of the
536
 
     *                           object being added.
537
 
     *
538
 
     * @return string  A unique ID for the new object.
539
 
     */
540
 
    protected function _makeKey(array $attributes)
541
 
    {
542
 
        return strval(new Horde_Support_Randomid());
543
 
    }
544
 
 
545
 
    /**
546
 
     * Builds a piece of a search query.
547
 
     *
548
 
     * @param string $glue      The glue to join the criteria (OR/AND).
549
 
     * @param array  $criteria  The array of criteria.
550
 
     *
551
 
     * @return array  An SQL fragment and a list of values suitable for binding
552
 
     *                as an array.
553
 
     */
554
 
    protected function _buildSearchQuery($glue, array $criteria)
555
 
    {
556
 
        $clause = '';
557
 
        $values = array();
558
 
 
559
 
        foreach ($criteria as $key => $vals) {
560
 
            if (!empty($vals['OR']) || !empty($vals['AND'])) {
561
 
                if (!empty($clause)) {
562
 
                    $clause .= ' ' . $glue . ' ';
563
 
                }
564
 
                $binds = $this->_buildSearchQuery(!empty($vals['OR']) ? 'OR' : 'AND', $vals);
565
 
                $clause .= '(' . $binds[0] . ')';
566
 
                $values = array_merge($values, $binds[1]);
567
 
            } else {
568
 
                if (isset($vals['field'])) {
569
 
                    if (!empty($clause)) {
570
 
                        $clause .= ' ' . $glue . ' ';
571
 
                    }
572
 
                    $rhs = $this->_convertToDriver($vals['test']);
573
 
                    $binds = $this->_db->buildClause($vals['field'], $vals['op'], $rhs, true, array('begin' => !empty($vals['begin'])));
574
 
                    if (is_array($binds)) {
575
 
                        $clause .= $binds[0];
576
 
                        $values = array_merge($values, $binds[1]);
577
 
                    } else {
578
 
                        $clause .= $binds;
579
 
                    }
580
 
                } else {
581
 
                    foreach ($vals as $test) {
582
 
                        if (!empty($test['OR']) || !empty($test['AND'])) {
583
 
                            if (!empty($clause)) {
584
 
                                $clause .= ' ' . $glue . ' ';
585
 
                            }
586
 
                            $binds = $this->_buildSearchQuery(!empty($vals['OR']) ? 'OR' : 'AND', $test);
587
 
                            $clause .= '(' . $binds[0] . ')';
588
 
                            $values = array_merge($values, $binds[1]);
589
 
                        } else {
590
 
                            if (!empty($clause)) {
591
 
                                $clause .= ' ' . $key . ' ';
592
 
                            }
593
 
                            $rhs = $this->_convertToDriver($test['test']);
594
 
                            if ($rhs == '' && $test['op'] == '=') {
595
 
                                $clause .= '(' . $this->_db->buildClause($test['field'], '=', $rhs) . ' OR ' . $test['field'] . ' IS NULL)';
596
 
                            } else {
597
 
                                $binds = $this->_db->buildClause($test['field'], $test['op'], $rhs, true, array('begin' => !empty($test['begin'])));
598
 
                                if (is_array($binds)) {
599
 
                                    $clause .= $binds[0];
600
 
                                    $values = array_merge($values, $binds[1]);
601
 
                                } else {
602
 
                                    $clause .= $binds;
603
 
                                }
604
 
                            }
605
 
                        }
606
 
                    }
607
 
                }
608
 
            }
609
 
        }
610
 
 
611
 
        return array($clause, $values);
612
 
    }
613
 
 
614
 
    /**
615
 
     * Converts a value from the driver's charset to the default charset.
616
 
     *
617
 
     * @param mixed $value  A value to convert.
618
 
     *
619
 
     * @return mixed  The converted value.
620
 
     */
621
 
    protected function _convertFromDriver($value)
622
 
    {
623
 
        return Horde_String::convertCharset($value, $this->_db->getOption('charset'), 'UTF-8');
624
 
    }
625
 
 
626
 
    /**
627
 
     * Converts a value from the default charset to the driver's charset.
628
 
     *
629
 
     * @param mixed $value  A value to convert.
630
 
     *
631
 
     * @return mixed  The converted value.
632
 
     */
633
 
    protected function _convertToDriver($value)
634
 
    {
635
 
        return Horde_String::convertCharset($value, 'UTF-8', $this->_db->getOption('charset'));
636
 
    }
637
 
 
638
 
    /**
639
 
     * Remove all entries owned by the specified user.
640
 
     *
641
 
     * @param string $user  The user's data to remove.
642
 
     *
643
 
     * @throws Horde_Exception_PermissionDenied
644
 
     */
645
 
    public function removeUserData($user)
646
 
    {
647
 
        // Make sure we are being called by an admin.
648
 
        if (!$GLOBALS['registry']->isAdmin()) {
649
 
            throw new Horde_Exception_PermissionDenied(_("Permission denied"));
650
 
        }
651
 
 
652
 
        $this->_deleteAll($user);
653
 
    }
654
 
 
655
 
    /**
656
 
     * Obtain Turba_List of items to get TimeObjects out of.
657
 
     *
658
 
     * @param Horde_Date $start  The starting date.
659
 
     * @param Horde_Date $end    The ending date.
660
 
     * @param string $field      The address book field containing the
661
 
     *                           timeObject information (birthday, anniversary)
662
 
     *
663
 
     * @return Turba_List  Object list.
664
 
     * @throws Turba_Exception
665
 
     */
666
 
    public function getTimeObjectTurbaList(Horde_Date $start, Horde_Date $end, $field)
667
 
    {
668
 
        $t_object = $this->toDriver($field);
669
 
        $criteria = $this->makesearch(
670
 
            array('__owner' => $this->getContactOwner()),
671
 
            'AND',
672
 
            array($this->toDriver('__owner') => true),
673
 
            false);
674
 
 
675
 
        // Limit to entries that actually contain a birthday and that are in the
676
 
        // date range we are looking for.
677
 
        $criteria['AND'][] = array(
678
 
            'field' => $t_object,
679
 
            'op' => '<>',
680
 
            'test' => ''
681
 
        );
682
 
 
683
 
        if ($start->year == $end->year) {
684
 
            $start = sprintf('%02d-%02d', $start->month, $start->mday);
685
 
            $end = sprintf('%02d-%02d', $end->month, $end->mday);
686
 
            $where = array('sql' => $t_object . ' IS NOT NULL AND SUBSTR('
687
 
                           . $t_object . ', 6, 5) BETWEEN ? AND ?',
688
 
                           'params' => array($start, $end));
689
 
        } else {
690
 
            $months = array();
691
 
            $diff = ($end->month + 12) - $start->month;
692
 
            $newDate = new Horde_Date(array(
693
 
                'month' => $start->month,
694
 
                'mday' => $start->mday,
695
 
                'year' => $start->year
696
 
            ));
697
 
            for ($i = 0; $i <= $diff; ++$i) {
698
 
                $months[] = sprintf('%02d', $newDate->month++);
699
 
            }
700
 
            $where = array('sql' => $t_object . ' IS NOT NULL AND SUBSTR('
701
 
                           . $t_object . ', 6, 2) IN ('
702
 
                           . str_repeat('?,', count($months) - 1) . '?)',
703
 
                           'params' => $months);
704
 
        }
705
 
 
706
 
        $fields_pre = array(
707
 
            '__key', '__type', '__owner', 'name', 'birthday', 'category',
708
 
            'anniversary'
709
 
        );
710
 
 
711
 
        $fields = array();
712
 
        foreach ($fields_pre as $field) {
713
 
            $result = $this->toDriver($field);
714
 
            if (is_array($result)) {
715
 
                foreach ($result as $composite_field) {
716
 
                    $composite_result = $this->toDriver($composite_field);
717
 
                    if ($composite_result) {
718
 
                        $fields[] = $composite_result;
719
 
                    }
720
 
                }
721
 
            } elseif ($result) {
722
 
                $fields[] = $result;
723
 
            }
724
 
        }
725
 
 
726
 
        return $this->_toTurbaObjects($this->_internalSearch($criteria, $fields, array(), $where));
727
 
    }
728
 
 
729
 
}