7902aca2 |
1 | <?php { |
2 | |
3 | /** |
4 | ** abook_database.php |
5 | ** |
6 | ** Backend for personal addressbook stored in a database, |
f435778e |
7 | ** accessed using the DB-classes in PEAR. |
7902aca2 |
8 | ** |
9 | ** IMPORTANT: The PEAR modules must be in the include path |
10 | ** for this class to work. |
11 | ** |
12 | ** An array with the following elements must be passed to |
13 | ** the class constructor (elements marked ? are optional): |
14 | ** |
15 | ** dsn => database DNS (see PEAR for syntax) |
16 | ** table => table to store addresses in (must exist) |
17 | ** owner => current user (owner of address data) |
18 | ** ? writeable => set writeable flag (true/false) |
19 | ** |
20 | ** The table used should have the following columns: |
21 | ** owner, nickname, firstname, lastname, email, label |
22 | ** The pair (owner,nickname) should be unique (primary key). |
23 | ** |
24 | ** NOTE. This class should not be used directly. Use the |
25 | ** "AddressBook" class instead. |
245a6892 |
26 | ** |
27 | ** $Id$ |
7902aca2 |
28 | **/ |
29 | |
b9bfd165 |
30 | require_once('DB.php'); |
7902aca2 |
31 | |
32 | class abook_database extends addressbook_backend { |
b9bfd165 |
33 | var $btype = 'local'; |
34 | var $bname = 'database'; |
7902aca2 |
35 | |
b9bfd165 |
36 | var $dsn = ''; |
37 | var $table = ''; |
38 | var $owner = ''; |
7902aca2 |
39 | var $dbh = false; |
40 | |
41 | var $writeable = true; |
42 | |
43 | // ========================== Private ======================= |
44 | |
45 | // Constructor |
46 | function abook_database($param) { |
701c9c6b |
47 | $this->sname = _("Personal address book"); |
7902aca2 |
48 | |
49 | if(is_array($param)) { |
91be2362 |
50 | if(empty($param['dsn']) || |
51 | empty($param['table']) || |
52 | empty($param['owner'])) |
53 | return $this->set_error('Invalid parameters'); |
7902aca2 |
54 | |
91be2362 |
55 | $this->dsn = $param['dsn']; |
56 | $this->table = $param['table']; |
57 | $this->owner = $param['owner']; |
7902aca2 |
58 | |
91be2362 |
59 | if(!empty($param['name'])) |
60 | $this->sname = $param['name']; |
7902aca2 |
61 | |
91be2362 |
62 | if(isset($param['writeable'])) |
63 | $this->writeable = $param['writeable']; |
7902aca2 |
64 | |
65 | $this->open(true); |
66 | } else { |
91be2362 |
67 | return $this->set_error('Invalid argument to constructor'); |
7902aca2 |
68 | } |
69 | } |
70 | |
71 | |
72 | // Open the database. New connection if $new is true |
73 | function open($new = false) { |
91be2362 |
74 | $this->error = ''; |
7902aca2 |
75 | |
76 | // Return true is file is open and $new is unset |
77 | if($this->dbh && !$new) |
78 | return true; |
79 | |
80 | // Close old file, if any |
81 | if($this->dbh) $this->close(); |
82 | |
83 | $dbh = DB::connect($this->dsn, true); |
84 | |
85 | if(DB::isError($dbh) || DB::isWarning($dbh)) |
701c9c6b |
86 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
87 | DB::errorMessage($dbh))); |
88 | |
89 | $this->dbh = $dbh; |
90 | return true; |
91 | } |
92 | |
93 | // Close the file and forget the filehandle |
94 | function close() { |
95 | $this->dbh->disconnect(); |
96 | $this->dbh = false; |
97 | } |
98 | |
99 | // ========================== Public ======================== |
100 | |
101 | // Search the file |
102 | function &search($expr) { |
103 | $ret = array(); |
104 | if(!$this->open()) |
105 | return false; |
106 | |
107 | // To be replaced by advanded search expression parsing |
108 | if(is_array($expr)) return; |
109 | |
110 | // Make regexp from glob'ed expression |
16a973d7 |
111 | $expr = str_replace('?', '_', $expr); |
112 | $expr = str_replace('*', '%', $expr); |
7902aca2 |
113 | $expr = $this->dbh->quoteString($expr); |
114 | $expr = "%$expr%"; |
115 | |
16a973d7 |
116 | $query = sprintf("SELECT * FROM %s WHERE owner='%s' AND " . |
117 | "(firstname LIKE '%s' OR lastname LIKE '%s')", |
7902aca2 |
118 | $this->table, $this->owner, $expr, $expr); |
119 | $res = $this->dbh->query($query); |
120 | |
121 | if(DB::isError($res)) |
701c9c6b |
122 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
123 | DB::errorMessage($res))); |
124 | |
125 | while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) { |
91be2362 |
126 | array_push($ret, array('nickname' => $row['nickname'], |
127 | 'name' => "$row[firstname] $row[lastname]", |
128 | 'firstname' => $row['firstname'], |
129 | 'lastname' => $row['lastname'], |
130 | 'email' => $row['email'], |
131 | 'label' => $row['label'], |
132 | 'backend' => $this->bnum, |
133 | 'source' => &$this->sname)); |
7902aca2 |
134 | } |
135 | return $ret; |
136 | } |
137 | |
138 | // Lookup alias |
139 | function &lookup($alias) { |
140 | if(empty($alias)) |
141 | return array(); |
142 | |
143 | $alias = strtolower($alias); |
144 | |
145 | if(!$this->open()) |
146 | return false; |
147 | |
16a973d7 |
148 | $query = sprintf("SELECT * FROM %s WHERE owner='%s' AND nickname='%s'", |
7902aca2 |
149 | $this->table, $this->owner, $alias); |
150 | |
151 | $res = $this->dbh->query($query); |
152 | |
153 | if(DB::isError($res)) |
701c9c6b |
154 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
155 | DB::errorMessage($res))); |
156 | |
157 | if ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) { |
91be2362 |
158 | return array('nickname' => $row['nickname'], |
159 | 'name' => "$row[firstname] $row[lastname]", |
160 | 'firstname' => $row['firstname'], |
161 | 'lastname' => $row['lastname'], |
162 | 'email' => $row['email'], |
163 | 'label' => $row['label'], |
164 | 'backend' => $this->bnum, |
165 | 'source' => &$this->sname); |
7902aca2 |
166 | } |
167 | |
168 | return array(); |
169 | } |
170 | |
171 | // List all addresses |
172 | function &list_addr() { |
173 | $ret = array(); |
174 | if(!$this->open()) |
175 | return false; |
176 | |
16a973d7 |
177 | $query = sprintf("SELECT * FROM %s WHERE owner='%s'", |
7902aca2 |
178 | $this->table, $this->owner); |
179 | |
180 | $res = $this->dbh->query($query); |
181 | |
182 | if(DB::isError($res)) |
701c9c6b |
183 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
184 | DB::errorMessage($res))); |
185 | |
186 | while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) { |
91be2362 |
187 | array_push($ret, array('nickname' => $row['nickname'], |
188 | 'name' => "$row[firstname] $row[lastname]", |
189 | 'firstname' => $row['firstname'], |
190 | 'lastname' => $row['lastname'], |
191 | 'email' => $row['email'], |
192 | 'label' => $row['label'], |
193 | 'backend' => $this->bnum, |
194 | 'source' => &$this->sname)); |
7902aca2 |
195 | } |
196 | return $ret; |
197 | } |
198 | |
199 | // Add address |
200 | function add($userdata) { |
91be2362 |
201 | if(!$this->writeable) |
701c9c6b |
202 | return $this->set_error(_("Addressbook is read-only")); |
7902aca2 |
203 | |
204 | if(!$this->open()) |
205 | return false; |
206 | |
207 | // See if user exist already |
91be2362 |
208 | $ret = $this->lookup($userdata['nickname']); |
7902aca2 |
209 | if(!empty($ret)) |
b9bfd165 |
210 | return $this->set_error(sprintf(_("User '%s' already exist"), |
91be2362 |
211 | $ret['nickname'])); |
7902aca2 |
212 | |
213 | // Create query |
16a973d7 |
214 | $query = sprintf("INSERT INTO %s (owner, nickname, firstname, " . |
91be2362 |
215 | "lastname, email, label) VALUES('%s','%s','%s'," . |
7902aca2 |
216 | "'%s','%s','%s')", |
217 | $this->table, $this->owner, |
91be2362 |
218 | $this->dbh->quoteString($userdata['nickname']), |
219 | $this->dbh->quoteString($userdata['firstname']), |
220 | $this->dbh->quoteString($userdata['lastname']), |
221 | $this->dbh->quoteString($userdata['email']), |
222 | $this->dbh->quoteString($userdata['label']) ); |
7902aca2 |
223 | |
224 | // Do the insert |
225 | $r = $this->dbh->simpleQuery($query); |
226 | if($r == DB_OK) return true; |
227 | |
228 | // Fail |
701c9c6b |
229 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
230 | DB::errorMessage($r))); |
231 | } |
232 | |
233 | // Delete address |
234 | function remove($alias) { |
235 | if(!$this->writeable) |
701c9c6b |
236 | return $this->set_error(_("Addressbook is read-only")); |
7902aca2 |
237 | |
238 | if(!$this->open()) |
239 | return false; |
240 | |
241 | // Create query |
16a973d7 |
242 | $query = sprintf("DELETE FROM %s WHERE owner='%s' AND (", |
7902aca2 |
243 | $this->table, $this->owner); |
244 | |
91be2362 |
245 | $sepstr = ''; |
7902aca2 |
246 | while(list($undef, $nickname) = each($alias)) { |
16a973d7 |
247 | $query .= sprintf("%s nickname='%s' ", $sepstr, |
7902aca2 |
248 | $this->dbh->quoteString($nickname)); |
91be2362 |
249 | $sepstr = 'OR'; |
7902aca2 |
250 | } |
91be2362 |
251 | $query .= ')'; |
7902aca2 |
252 | |
253 | // Delete entry |
254 | $r = $this->dbh->simpleQuery($query); |
255 | if($r == DB_OK) return true; |
256 | |
257 | // Fail |
701c9c6b |
258 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
259 | DB::errorMessage($r))); |
260 | } |
261 | |
262 | // Modify address |
263 | function modify($alias, $userdata) { |
264 | if(!$this->writeable) |
701c9c6b |
265 | return $this->set_error(_("Addressbook is read-only")); |
7902aca2 |
266 | |
267 | if(!$this->open()) |
268 | return false; |
269 | |
270 | // See if user exist |
271 | $ret = $this->lookup($alias); |
272 | if(empty($ret)) |
701c9c6b |
273 | return $this->set_error(sprintf(_("User '%s' does not exist"), |
7902aca2 |
274 | $alias)); |
275 | |
276 | // Create query |
277 | $query = sprintf("UPDATE %s SET nickname='%s', firstname='%s', ". |
278 | "lastname='%s', email='%s', label='%s' ". |
279 | "WHERE owner='%s' AND nickname='%s'", |
280 | $this->table, |
91be2362 |
281 | $this->dbh->quoteString($userdata['nickname']), |
282 | $this->dbh->quoteString($userdata['firstname']), |
283 | $this->dbh->quoteString($userdata['lastname']), |
284 | $this->dbh->quoteString($userdata['email']), |
285 | $this->dbh->quoteString($userdata['label']), |
7902aca2 |
286 | $this->owner, |
287 | $this->dbh->quoteString($alias) ); |
288 | |
289 | // Do the insert |
290 | $r = $this->dbh->simpleQuery($query); |
291 | if($r == DB_OK) return true; |
292 | |
293 | // Fail |
701c9c6b |
294 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
295 | DB::errorMessage($r))); |
296 | } |
297 | } // End of class abook_database |
298 | |
299 | } ?> |