1: <?php
  2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13: 
 14: class Luxor_Driver_sql extends Luxor_Driver {
 15: 
 16:      17:  18:  19:  20: 
 21:     var $_params = array();
 22: 
 23:      24:  25:  26:  27: 
 28:     var $_db;
 29: 
 30:      31:  32:  33:  34: 
 35:     var $_source;
 36: 
 37:      38:  39:  40:  41: 
 42:     var $_connected = false;
 43: 
 44:      45:  46:  47:  48: 
 49:     var $_symcache = array();
 50: 
 51:      52:  53:  54:  55: 
 56:     var $_decIdcache = array();
 57: 
 58:      59:  60:  61:  62:  63: 
 64:     function Luxor_Driver_sql($source, $params = array())
 65:     {
 66:         $this->_source = $source;
 67:         $this->_params = $params;
 68:     }
 69: 
 70:      71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82: 
 83:     function index($symname, $fileId, $line, $langid, $type)
 84:     {
 85:         $this->_connect();
 86: 
 87:         $symid = $this->symid($symname);
 88:         if (is_a($symid, 'PEAR_Error')) {
 89:             return $symid;
 90:         }
 91: 
 92:          93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 
103: 
104:         $query = 'INSERT INTO luxor_indexes (symid, fileid, line, declid)' .
105:                  ' VALUES (?, ?, ?, ?)';
106:         $values = array($symid, $fileId, $line, $this->getDecId($langid, $type));
107:         return $this->_db->query($query, $values);
108:     }
109: 
110:     111: 112: 113: 114: 115: 116: 117: 118: 119: 
120:     function reference($symname, $fileId, $line)
121:     {
122:         $this->_connect();
123: 
124:         $result = $this->_db->query('INSERT INTO luxor_usage (fileid, line, symid) VALUES (?, ?, ?)',
125:                                     array($fileId, $line, $this->symid($symname)));
126:         return $result;
127:     }
128: 
129:     130: 131: 132: 133: 134: 135: 136: 
137:     function fileId($filename, $tag = '')
138:     {
139:         static $files = array();
140: 
141:         
142:         if (isset($files[$filename])) {
143:             return $files[$filename];
144:         }
145: 
146:         $this->_connect();
147: 
148:         
149:         $query = 'SELECT fileid FROM luxor_files' .
150:                  ' WHERE tag = ? AND source = ? AND filename = ?';
151:         $values = array($tag, $this->_source, $filename);
152: 
153:         $fileId = $this->_db->getOne($query, $values);
154:         if (empty($fileId) || is_a($fileId, 'PEAR_Error')) {
155:             return false;
156:         }
157:         $files[$filename] = $fileId;
158: 
159:         return $fileId;
160:     }
161: 
162:     163: 164: 165: 166: 167: 168: 169: 170: 
171:     function createFileId($filename, $tag = '', $lastmodified)
172:     {
173:         $this->_connect();
174: 
175:         $fileId = $this->_db->nextId('luxor_files');
176:         if (is_a($fileId, 'PEAR_Error')) {
177:             return $fileId;
178:         }
179: 
180:         
181:         $query = 'INSERT INTO luxor_files (fileid, filename, source, tag, lastmodified) VALUES (?, ?, ?, ?, ?)';
182:         $values = array((int)$fileId,
183:                         $filename,
184:                         $this->_source,
185:                         $tag,
186:                         $lastmodified);
187: 
188:         $result = $this->_db->query($query, $values);
189:         if (is_a($result, 'PEAR_Error')) {
190:             return $result;
191:         }
192: 
193:         return $fileId;
194:     }
195: 
196:     197: 198: 199: 200: 201: 202: 
203:     function symid($symname)
204:     {
205:         
206:         if (!isset($this->_symcache[$symname])) {
207:             $this->_connect();
208:             
209:             $query = 'SELECT symid FROM luxor_symbols' .
210:                      ' WHERE source = ? AND symname = ?';
211:             $values = array($this->_source, $symname);
212:             $symid = $this->_db->getOne($query, $values);
213:             if (is_null($symid) || is_a($symid, 'PEAR_Error')) {
214:                 
215:                 $symid = $this->_db->nextId('luxor_symbols');
216:                 if (is_a($symid, 'PEAR_Error')) {
217:                     return $symid;
218:                 }
219:                 $result = $this->_db->query('INSERT INTO luxor_symbols (symid, symname, source) VALUES (?, ?, ?)',
220:                                             array((int)$symid, $symname, $this->_source));
221:                 if (is_a($result, 'PEAR_Error')) {
222:                     return $result;
223:                 }
224:             }
225:             $this->_symcache[$symname] = $symid;
226:         }
227: 
228:         return $this->_symcache[$symname];
229:     }
230: 
231:     232: 233: 234: 235: 236: 237: 
238:     function symname($symid)
239:     {
240:         
241:         $this->_connect();
242: 
243:         if (in_array($symid, $this->_symcache)) {
244:             return array_key($symid, $this->_symcache);
245:         }
246: 
247:         $query = 'SELECT symname FROM luxor_symbols WHERE symid = ?';
248:         $values = array($symid);
249:         $symname = $this->_db->getOne($query, $values);
250:         $this->_symcache[$symname] = $symid;
251: 
252:         return $symname;
253:     }
254: 
255:     256: 257: 258: 259: 260: 261: 
262:     function isSymbol($symname, $altsources = array())
263:     {
264:         if (!isset($this->_symcache[$symname])) {
265:             $this->_connect();
266: 
267:             $altsql = '';
268:             $altvalues = array();
269:             if (!is_array($altsources)) {
270:                 $altsources = array($altsources);
271:             }
272:             foreach ($altsources as $source) {
273:                 $altsql .= ' OR source = ?';
274:                 $altvalues[] = $source;
275:             }
276: 
277:             array_unshift($altvalues, $this->_source);
278:             $values = $altvalues;
279:             $values[] = $symname;
280: 
281:             $symid = $this->_db->getOne('SELECT symid FROM luxor_symbols' .
282:                                         ' WHERE (source = ?' . $altsql . ')' .
283:                                         ' AND symname = ?',
284:                                         $values);
285:             $this->_symcache[$symname] = $symid;
286:         }
287: 
288:         return $this->_symcache[$symname];
289:     }
290: 
291:     292: 293: 294: 295: 296: 297: 298: 299: 
300:     function toIndex($fileId)
301:     {
302:         $this->_connect();
303: 
304:         $status = $this->_db->getOne('SELECT status FROM luxor_status' .
305:                                      ' WHERE fileid = ?',
306:                                      array($fileId));
307:         if (empty($status)) {
308:             $this->_db->query('INSERT INTO luxor_status (fileid, status)' .
309:                               ' VALUES (?, 0)',
310:                               array($fileId + 0));
311:         }
312:         $query = 'UPDATE luxor_status SET status = 1' .
313:                  ' WHERE fileid = ? AND status <= 0';
314:         $values = array($fileId);
315:         return $this->_db->query($query, $values);
316:     }
317: 
318:     319: 320: 321: 322: 323: 324: 325: 326: 
327:     function toReference($fileId)
328:     {
329:         $this->_connect();
330: 
331:         $query = 'UPDATE luxor_status SET status = 2' .
332:                  ' WHERE fileid = ? AND status <= 1';
333:         $values = array($fileId);
334:         return $this->_db->query($query, $values);
335:     }
336: 
337:     338: 339: 340: 341: 342: 343: 
344:     function getLastModified($filename)
345:     {
346:         static $lastModified;
347: 
348:         if (isset($lastModified[$filename])) {
349:             return $lastModified[$filename];
350:         }
351: 
352:         $this->_connect();
353:         $query = 'SELECT lastmodified FROM luxor_files' .
354:                  ' WHERE source = ? AND filename = ?';
355:         $values = array($this->_source, $filename);
356:         $res = $this->_db->getOne($query, $values);
357:         $lastModified[$filename] = is_a($res, 'PEAR_Error') ? 0 : $res;
358: 
359:         return $lastModified[$filename];
360:     }
361: 
362:     363: 364: 365: 366: 367: 368: 
369:     function clearCache()
370:     {
371:         $this->_symcache = array();
372:     }
373: 
374:     375: 376: 377: 378: 379: 
380:     function clearIndex()
381:     {
382:         $this->_connect();
383: 
384:         $this->_db->query('DELETE FROM luxor_declarations');
385:         $this->_db->query('DELETE FROM luxor_files');
386:         $this->_db->query('DELETE FROM luxor_indexes');
387:         $this->_db->query('DELETE FROM luxor_status');
388:         $this->_db->query('DELETE FROM luxor_symbols');
389:         $this->_db->query('DELETE FROM luxor_usage');
390:     }
391: 
392:     393: 394: 395: 396: 397: 398: 399: 
400:     function getDecId($lang, $string)
401:     {
402:         $this->_connect();
403: 
404:         if (!isset($this->_decIdcache[$lang])) {
405:             $this->_decIdcache[$lang] = array();
406:         }
407: 
408:         if (!isset($this->_decIdcache[$lang][$string])) {
409:             $query = 'SELECT declid FROM luxor_declarations' .
410:                      ' WHERE langid = ? AND declaration = ?';
411:             $values = array($lang, $string);
412:             $decId = $this->_db->getOne($query, $values);
413:             if (is_null($decId) || is_a($decId, 'PEAR_Error')) {
414:                 
415:                 $decId = $this->_db->nextId('luxor_declarations');
416:                 if (is_a($decId, 'PEAR_Error')) {
417:                     return $decId;
418:                 }
419:                 $this->_db->query('INSERT INTO luxor_declarations (declid, langid, declaration)' .
420:                                   ' VALUES (?, ?, ?)',
421:                                   array((int)$decId, $lang, $string));
422:             }
423:             $this->_decIdcache[$lang][$string] = $decId;
424:         }
425: 
426:         return $this->_decIdcache[$lang][$string];
427:     }
428: 
429:     430: 431: 432: 433: 434: 435: 436: 437: 
438:     function getIndex($symid, $tag = '')
439:     {
440:         $this->_connect();
441:         $query = 'SELECT filename, line, declaration FROM ' .
442:                  'luxor_files, luxor_indexes, luxor_declarations WHERE ' .
443:                  'luxor_files.fileid = luxor_indexes.fileid AND ' . 
444:                  'luxor_indexes.declid = luxor_declarations.declid AND ' . 
445:                  'luxor_indexes.symid = ? AND ' .
446:                  'luxor_files.tag = ? AND ' .
447:                  'luxor_files.source = ?';
448:         $values = array((int)$symid, $tag, $this->_source);
449: 
450:         return $this->_db->getAll($query, $values, DB_FETCHMODE_ASSOC);
451:     }
452: 
453:     454: 455: 456: 457: 458: 459: 460: 
461:     function getReference($symid, $tag = '')
462:     {
463:         $this->_connect();
464:         $query = 'SELECT filename, line FROM ' .
465:                  'luxor_usage, luxor_files WHERE ' .
466:                  'luxor_usage.fileid = luxor_files.fileid AND ' .
467:                  'luxor_usage.symid = ? AND ' .
468:                  'luxor_files.tag = ? AND ' .
469:                  'luxor_files.source = ?';
470:         $values = array((int)$symid, $tag, $this->_source);
471: 
472:         return $this->_db->getAll($query, $values, DB_FETCHMODE_ASSOC);
473:     }
474: 
475:     476: 477: 478: 479: 480: 481: 
482:     function searchSymbols($symbol)
483:     {
484:         $this->_connect();
485:         $query = 'SELECT symid, symid FROM luxor_symbols WHERE symname LIKE ?';
486:         $values = array($symbol . '%');
487: 
488:         return $this->_db->getAssoc($query, false, $values);
489:     }
490: 
491:     492: 493: 494: 495: 496: 497: 
498:     function getSourceBySymbol($symid)
499:     {
500:         $this->_connect();
501: 
502:         return $this->_db->getOne('SELECT source FROM luxor_symbols' .
503:                                   ' WHERE symid = ?',
504:                                   array($symid));
505:     }
506: 
507:     508: 509: 510: 511: 
512:     function _connect()
513:     {
514:         if (!$this->_connected) {
515:             $this->_db = $GLOBALS['injector']->getInstance('Horde_Core_Factory_DbPear')->create('rw', 'luxor', 'storage');
516:             $this->_connected = true;
517:         }
518: 
519:         return true;
520:     }
521: 
522: }
523: