2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 * Database enrolment plugin.
20 * This plugin synchronises enrolment and roles with external database table.
23 * @subpackage database
24 * @copyright 2010 Petr Skoda {@link http://skodak.org}
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 defined('MOODLE_INTERNAL') ||
die();
31 * Database enrolment plugin implementation.
32 * @author Petr Skoda - based on code by Martin Dougiamas, Martin Langhoff and others
33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 class enrol_database_plugin
extends enrol_plugin
{
37 * Is it possible to delete enrol instance via standard UI?
39 * @param object $instance
42 public function instance_deleteable($instance) {
43 if (!enrol_is_enabled('database')) {
46 if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('remoteenroltable') or !$this->get_config('remotecoursefield') or !$this->get_config('remoteuserfield')) {
50 //TODO: connect to external system and make sure no users are to be enrolled in this course
55 * Does this plugin allow manual unenrolment of a specific user?
56 * Yes, but only if user suspended...
58 * @param stdClass $instance course enrol instance
59 * @param stdClass $ue record from user_enrolments table
61 * @return bool - true means user with 'enrol/xxx:unenrol' may unenrol this user, false means nobody may touch this user enrolment
63 public function allow_unenrol_user(stdClass
$instance, stdClass
$ue) {
64 if ($ue->status
== ENROL_USER_SUSPENDED
) {
72 * Gets an array of the user enrolment actions
74 * @param course_enrolment_manager $manager
75 * @param stdClass $ue A user enrolment object
76 * @return array An array of user_enrolment_actions
78 public function get_user_enrolment_actions(course_enrolment_manager
$manager, $ue) {
80 $context = $manager->get_context();
81 $instance = $ue->enrolmentinstance
;
82 $params = $manager->get_moodlepage()->url
->params();
83 $params['ue'] = $ue->id
;
84 if ($this->allow_unenrol_user($instance, $ue) && has_capability('enrol/database:unenrol', $context)) {
85 $url = new moodle_url('/enrol/unenroluser.php', $params);
86 $actions[] = new user_enrolment_action(new pix_icon('t/delete', ''), get_string('unenrol', 'enrol'), $url, array('class'=>'unenrollink', 'rel'=>$ue->id
));
92 * Forces synchronisation of user enrolments with external database,
93 * does not create new courses.
95 * @param object $user user record
98 public function sync_user_enrolments($user) {
101 // we do not create courses here intentionally because it requires full sync and is slow
102 if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('remoteenroltable') or !$this->get_config('remotecoursefield') or !$this->get_config('remoteuserfield')) {
106 $table = $this->get_config('remoteenroltable');
107 $coursefield = strtolower($this->get_config('remotecoursefield'));
108 $userfield = strtolower($this->get_config('remoteuserfield'));
109 $rolefield = strtolower($this->get_config('remoterolefield'));
111 $localrolefield = $this->get_config('localrolefield');
112 $localuserfield = $this->get_config('localuserfield');
113 $localcoursefield = $this->get_config('localcoursefield');
115 $unenrolaction = $this->get_config('unenrolaction');
116 $defaultrole = $this->get_config('defaultrole');
118 $ignorehidden = $this->get_config('ignorehiddencourses');
120 if (!is_object($user) or !property_exists($user, 'id')) {
121 throw new coding_exception('Invalid $user parameter in sync_user_enrolments()');
124 if (!property_exists($user, $localuserfield)) {
125 debugging('Invalid $user parameter in sync_user_enrolments(), missing '.$localuserfield);
126 $user = $DB->get_record('user', array('id'=>$user->id
));
129 // create roles mapping
130 $allroles = get_all_roles();
131 if (!isset($allroles[$defaultrole])) {
135 foreach ($allroles as $role) {
136 $roles[$role->$localrolefield] = $role->id
;
140 $instances = array();
142 if (!$extdb = $this->db_init()) {
143 // can not connect to database, sorry
147 // read remote enrols and create instances
148 $sql = $this->db_get_sql($table, array($userfield=>$user->$localuserfield), array(), false);
150 if ($rs = $extdb->Execute($sql)) {
152 while ($fields = $rs->FetchRow()) {
153 $fields = array_change_key_case($fields, CASE_LOWER
);
154 $fields = $this->db_decode($fields);
156 if (empty($fields[$coursefield])) {
157 // missing course info
160 if (!$course = $DB->get_record('course', array($localcoursefield=>$fields[$coursefield]), 'id,visible')) {
163 if (!$course->visible
and $ignorehidden) {
167 if (empty($fields[$rolefield]) or !isset($roles[$fields[$rolefield]])) {
172 $roleid = $defaultrole;
174 $roleid = $roles[$fields[$rolefield]];
177 if (empty($enrols[$course->id
])) {
178 $enrols[$course->id
] = array();
180 $enrols[$course->id
][] = $roleid;
182 if ($instance = $DB->get_record('enrol', array('courseid'=>$course->id
, 'enrol'=>'database'), '*', IGNORE_MULTIPLE
)) {
183 $instances[$course->id
] = $instance;
187 $enrolid = $this->add_instance($course);
188 $instances[$course->id
] = $DB->get_record('enrol', array('id'=>$enrolid));
194 // bad luck, something is wrong with the db connection
199 // enrol user into courses and sync roles
200 foreach ($enrols as $courseid => $roles) {
201 if (!isset($instances[$courseid])) {
205 $instance = $instances[$courseid];
207 if ($e = $DB->get_record('user_enrolments', array('userid'=>$user->id
, 'enrolid'=>$instance->id
))) {
208 // reenable enrolment when previously disable enrolment refreshed
209 if ($e->status
== ENROL_USER_SUSPENDED
) {
210 $this->update_user_enrol($instance, $user->id
, ENROL_USER_ACTIVE
);
213 $roleid = reset($roles);
214 $this->enrol_user($instance, $user->id
, $roleid, 0, 0, ENROL_USER_ACTIVE
);
217 if (!$context = context_course
::instance($instance->courseid
, IGNORE_MISSING
)) {
221 $current = $DB->get_records('role_assignments', array('contextid'=>$context->id
, 'userid'=>$user->id
, 'component'=>'enrol_database', 'itemid'=>$instance->id
), '', 'id, roleid');
224 foreach ($current as $r) {
225 if (in_array($r->roleid
, $roles)) {
226 $existing[$r->roleid
] = $r->roleid
;
228 role_unassign($r->roleid
, $user->id
, $context->id
, 'enrol_database', $instance->id
);
231 foreach ($roles as $rid) {
232 if (!isset($existing[$rid])) {
233 role_assign($rid, $user->id
, $context->id
, 'enrol_database', $instance->id
);
238 // unenrol as necessary
239 $sql = "SELECT e.*, c.visible AS cvisible, ue.status AS ustatus
241 JOIN {user_enrolments} ue ON ue.enrolid = e.id
242 JOIN {course} c ON c.id = e.courseid
243 WHERE ue.userid = :userid AND e.enrol = 'database'";
244 $rs = $DB->get_recordset_sql($sql, array('userid'=>$user->id
));
245 foreach ($rs as $instance) {
246 if (!$instance->cvisible
and $ignorehidden) {
250 if (!$context = context_course
::instance($instance->courseid
, IGNORE_MISSING
)) {
255 if (!empty($enrols[$instance->courseid
])) {
256 // we want this user enrolled
260 // deal with enrolments removed from external table
261 if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL
) {
263 $this->unenrol_user($instance, $user->id
);
265 } else if ($unenrolaction == ENROL_EXT_REMOVED_KEEP
) {
266 // keep - only adding enrolments
268 } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND
or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES
) {
270 if ($instance->ustatus
!= ENROL_USER_SUSPENDED
) {
271 $this->update_user_enrol($instance, $user->id
, ENROL_USER_SUSPENDED
);
273 if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES
) {
274 role_unassign_all(array('contextid'=>$context->id
, 'userid'=>$user->id
, 'component'=>'enrol_database', 'itemid'=>$instance->id
));
282 * Forces synchronisation of all enrolments with external database.
284 * @param bool $verbose
285 * @return int 0 means success, 1 db connect failure, 2 db read failure
287 public function sync_enrolments($verbose = false) {
290 // we do not create courses here intentionally because it requires full sync and is slow
291 if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('remoteenroltable') or !$this->get_config('remotecoursefield') or !$this->get_config('remoteuserfield')) {
293 mtrace('User enrolment synchronisation skipped.');
299 mtrace('Starting user enrolment synchronisation...');
302 if (!$extdb = $this->db_init()) {
303 mtrace('Error while communicating with external enrolment database');
307 // we may need a lot of memory here
309 raise_memory_limit(MEMORY_HUGE
);
311 // second step is to sync instances and users
312 $table = $this->get_config('remoteenroltable');
313 $coursefield = strtolower($this->get_config('remotecoursefield'));
314 $userfield = strtolower($this->get_config('remoteuserfield'));
315 $rolefield = strtolower($this->get_config('remoterolefield'));
317 $localrolefield = $this->get_config('localrolefield');
318 $localuserfield = $this->get_config('localuserfield');
319 $localcoursefield = $this->get_config('localcoursefield');
321 $unenrolaction = $this->get_config('unenrolaction');
322 $defaultrole = $this->get_config('defaultrole');
324 // create roles mapping
325 $allroles = get_all_roles();
326 if (!isset($allroles[$defaultrole])) {
330 foreach ($allroles as $role) {
331 $roles[$role->$localrolefield] = $role->id
;
334 // get a list of courses to be synced that are in external table
335 $externalcourses = array();
336 $sql = $this->db_get_sql($table, array(), array($coursefield), true);
337 if ($rs = $extdb->Execute($sql)) {
339 while ($mapping = $rs->FetchRow()) {
340 $mapping = reset($mapping);
341 $mapping = $this->db_decode($mapping);
342 if (empty($mapping)) {
346 $externalcourses[$mapping] = true;
351 mtrace('Error reading data from the external enrolment table');
355 $preventfullunenrol = empty($externalcourses);
356 if ($preventfullunenrol and $unenrolaction == ENROL_EXT_REMOVED_UNENROL
) {
357 mtrace(' Preventing unenrolment of all current users, because it might result in major data loss, there has to be at least one record in external enrol table, sorry.');
360 // first find all existing courses with enrol instance
362 $sql = "SELECT c.id, c.visible, c.$localcoursefield AS mapping, e.id AS enrolid, c.shortname
364 JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')";
365 $rs = $DB->get_recordset_sql($sql); // watch out for idnumber duplicates
366 foreach ($rs as $course) {
367 if (empty($course->mapping
)) {
370 $existing[$course->mapping
] = $course;
371 unset($externalcourses[$course->mapping
]);
375 // add necessary enrol instances that are not present yet
378 if ($localcoursefield !== 'id') {
379 $localnotempty = "AND c.$localcoursefield <> :lcfe";
380 $params['lcfe'] = $DB->sql_empty();
382 $sql = "SELECT c.id, c.visible, c.$localcoursefield AS mapping, c.shortname
384 LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')
385 WHERE e.id IS NULL $localnotempty";
386 $rs = $DB->get_recordset_sql($sql, $params);
387 foreach ($rs as $course) {
388 if (empty($course->mapping
)) {
391 if (!isset($externalcourses[$course->mapping
])) {
392 // Course not synced or duplicate.
395 $course->enrolid
= $this->add_instance($course);
396 $existing[$course->mapping
] = $course;
397 unset($externalcourses[$course->mapping
]);
401 // Print list of missing courses.
402 if ($verbose and $externalcourses) {
403 $list = implode(', ', array_keys($externalcourses));
404 mtrace(" error: following courses do not exist - $list");
409 unset($externalcourses);
412 $ignorehidden = $this->get_config('ignorehiddencourses');
413 $sqlfields = array($userfield);
415 $sqlfields[] = $rolefield;
417 foreach ($existing as $course) {
418 if ($ignorehidden and !$course->visible
) {
421 if (!$instance = $DB->get_record('enrol', array('id'=>$course->enrolid
))) {
424 $context = context_course
::instance($course->id
);
426 // get current list of enrolled users with their roles
427 $current_roles = array();
428 $current_status = array();
429 $user_mapping = array();
430 $sql = "SELECT u.$localuserfield AS mapping, u.id, ue.status, ue.userid, ra.roleid
432 JOIN {user_enrolments} ue ON (ue.userid = u.id AND ue.enrolid = :enrolid)
433 JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.itemid = ue.enrolid AND ra.component = 'enrol_database')
434 WHERE u.deleted = 0";
435 $params = array('enrolid'=>$instance->id
);
436 if ($localuserfield === 'username') {
437 $sql .= " AND u.mnethostid = :mnethostid";
438 $params['mnethostid'] = $CFG->mnet_localhost_id
;
440 $rs = $DB->get_recordset_sql($sql, $params);
441 foreach ($rs as $ue) {
442 $current_roles[$ue->userid
][$ue->roleid
] = $ue->roleid
;
443 $current_status[$ue->userid
] = $ue->status
;
444 $user_mapping[$ue->mapping
] = $ue->userid
;
448 // get list of users that need to be enrolled and their roles
449 $requested_roles = array();
450 $sql = $this->db_get_sql($table, array($coursefield=>$course->mapping
), $sqlfields);
451 if ($rs = $extdb->Execute($sql)) {
453 $usersearch = array('deleted' => 0);
454 if ($localuserfield === 'username') {
455 $usersearch['mnethostid'] = $CFG->mnet_localhost_id
;
457 while ($fields = $rs->FetchRow()) {
458 $fields = array_change_key_case($fields, CASE_LOWER
);
459 if (empty($fields[$userfield])) {
461 mtrace(" error: skipping user without mandatory $localuserfield in course '$course->mapping'");
465 $mapping = $fields[$userfield];
466 if (!isset($user_mapping[$mapping])) {
467 $usersearch[$localuserfield] = $mapping;
468 if (!$user = $DB->get_record('user', $usersearch, 'id', IGNORE_MULTIPLE
)) {
470 mtrace(" error: skipping unknown user $localuserfield '$mapping' in course '$course->mapping'");
474 $user_mapping[$mapping] = $user->id
;
477 $userid = $user_mapping[$mapping];
479 if (empty($fields[$rolefield]) or !isset($roles[$fields[$rolefield]])) {
482 mtrace(" error: skipping user '$userid' in course '$course->mapping' - missing course and default role");
486 $roleid = $defaultrole;
488 $roleid = $roles[$fields[$rolefield]];
491 $requested_roles[$userid][$roleid] = $roleid;
496 mtrace(" error: skipping course '$course->mapping' - could not match with external database");
499 unset($user_mapping);
501 // enrol all users and sync roles
502 foreach ($requested_roles as $userid=>$userroles) {
503 foreach ($userroles as $roleid) {
504 if (empty($current_roles[$userid])) {
505 $this->enrol_user($instance, $userid, $roleid, 0, 0, ENROL_USER_ACTIVE
);
506 $current_roles[$userid][$roleid] = $roleid;
507 $current_status[$userid] = ENROL_USER_ACTIVE
;
509 mtrace(" enrolling: $userid ==> $course->shortname as ".$allroles[$roleid]->shortname
);
514 // assign extra roles
515 foreach ($userroles as $roleid) {
516 if (empty($current_roles[$userid][$roleid])) {
517 role_assign($roleid, $userid, $context->id
, 'enrol_database', $instance->id
);
518 $current_roles[$userid][$roleid] = $roleid;
520 mtrace(" assigning roles: $userid ==> $course->shortname as ".$allroles[$roleid]->shortname
);
525 // unassign removed roles
526 foreach($current_roles[$userid] as $cr) {
527 if (empty($userroles[$cr])) {
528 role_unassign($cr, $userid, $context->id
, 'enrol_database', $instance->id
);
529 unset($current_roles[$userid][$cr]);
531 mtrace(" unsassigning roles: $userid ==> $course->shortname");
536 // reenable enrolment when previously disable enrolment refreshed
537 if ($current_status[$userid] == ENROL_USER_SUSPENDED
) {
538 $this->update_user_enrol($instance, $userid, ENROL_USER_ACTIVE
);
540 mtrace(" unsuspending: $userid ==> $course->shortname");
545 // deal with enrolments removed from external table
546 if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL
) {
547 if (!$preventfullunenrol) {
549 foreach ($current_status as $userid=>$status) {
550 if (isset($requested_roles[$userid])) {
553 $this->unenrol_user($instance, $userid);
555 mtrace(" unenrolling: $userid ==> $course->shortname");
560 } else if ($unenrolaction == ENROL_EXT_REMOVED_KEEP
) {
561 // keep - only adding enrolments
563 } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND
or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES
) {
565 foreach ($current_status as $userid=>$status) {
566 if (isset($requested_roles[$userid])) {
569 if ($status != ENROL_USER_SUSPENDED
) {
570 $this->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED
);
572 mtrace(" suspending: $userid ==> $course->shortname");
575 if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES
) {
576 role_unassign_all(array('contextid'=>$context->id
, 'userid'=>$userid, 'component'=>'enrol_database', 'itemid'=>$instance->id
));
578 mtrace(" unsassigning all roles: $userid ==> $course->shortname");
585 // close db connection
589 mtrace('...user enrolment synchronisation finished.');
596 * Performs a full sync with external database.
598 * First it creates new courses if necessary, then
599 * enrols and unenrols users.
601 * @param bool $verbose
602 * @return int 0 means success, 1 db connect failure, 4 db read failure
604 public function sync_courses($verbose = false) {
607 // make sure we sync either enrolments or courses
608 if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('newcoursetable') or !$this->get_config('newcoursefullname') or !$this->get_config('newcourseshortname')) {
610 mtrace('Course synchronisation skipped.');
616 mtrace('Starting course synchronisation...');
619 // we may need a lot of memory here
621 raise_memory_limit(MEMORY_HUGE
);
623 if (!$extdb = $this->db_init()) {
624 mtrace('Error while communicating with external enrolment database');
628 // first create new courses
629 $table = $this->get_config('newcoursetable');
630 $fullname = strtolower($this->get_config('newcoursefullname'));
631 $shortname = strtolower($this->get_config('newcourseshortname'));
632 $idnumber = strtolower($this->get_config('newcourseidnumber'));
633 $category = strtolower($this->get_config('newcoursecategory'));
635 $localcategoryfield = $this->get_config('localcategoryfield', 'id');
637 $sqlfields = array($fullname, $shortname);
639 $sqlfields[] = $category;
642 $sqlfields[] = $idnumber;
644 $sql = $this->db_get_sql($table, array(), $sqlfields, true);
645 $createcourses = array();
646 if ($rs = $extdb->Execute($sql)) {
648 while ($fields = $rs->FetchRow()) {
649 $fields = array_change_key_case($fields, CASE_LOWER
);
650 $fields = $this->db_decode($fields);
651 if (empty($fields[$shortname]) or empty($fields[$fullname])) {
653 mtrace(' error: invalid external course record, shortname and fullname are mandatory: ' . json_encode($fields)); // hopefully every geek can read JS, right?
657 if ($DB->record_exists('course', array('shortname'=>$fields[$shortname]))) {
661 // allow empty idnumber but not duplicates
662 if ($idnumber and $fields[$idnumber] !== '' and $fields[$idnumber] !== null and $DB->record_exists('course', array('idnumber'=>$fields[$idnumber]))) {
664 mtrace(' error: duplicate idnumber, can not create course: '.$fields[$shortname].' ['.$fields[$idnumber].']');
668 if ($category and !$coursecategory = $DB->get_record('course_categories', array($localcategoryfield=>$fields[$category]), 'id')) {
670 mtrace(' error: invalid category '.$localcategoryfield.', can not create course: '.$fields[$shortname]);
674 $course = new stdClass();
675 $course->fullname
= $fields[$fullname];
676 $course->shortname
= $fields[$shortname];
677 $course->idnumber
= $idnumber ?
$fields[$idnumber] : '';
678 $course->category
= $category ?
$coursecategory->id
: NULL;
679 $createcourses[] = $course;
684 mtrace('Error reading data from the external course table');
688 if ($createcourses) {
689 require_once("$CFG->dirroot/course/lib.php");
691 $templatecourse = $this->get_config('templatecourse');
692 $defaultcategory = $this->get_config('defaultcategory');
695 if ($templatecourse) {
696 if ($template = $DB->get_record('course', array('shortname'=>$templatecourse))) {
697 unset($template->id
);
698 unset($template->fullname
);
699 unset($template->shortname
);
700 unset($template->idnumber
);
703 mtrace(" can not find template for new course!");
708 $courseconfig = get_config('moodlecourse');
709 $template = new stdClass();
710 $template->summary
= '';
711 $template->summaryformat
= FORMAT_HTML
;
712 $template->format
= $courseconfig->format
;
713 $template->numsections
= $courseconfig->numsections
;
714 $template->hiddensections
= $courseconfig->hiddensections
;
715 $template->newsitems
= $courseconfig->newsitems
;
716 $template->showgrades
= $courseconfig->showgrades
;
717 $template->showreports
= $courseconfig->showreports
;
718 $template->maxbytes
= $courseconfig->maxbytes
;
719 $template->groupmode
= $courseconfig->groupmode
;
720 $template->groupmodeforce
= $courseconfig->groupmodeforce
;
721 $template->visible
= $courseconfig->visible
;
722 $template->lang
= $courseconfig->lang
;
723 $template->groupmodeforce
= $courseconfig->groupmodeforce
;
725 if (!$DB->record_exists('course_categories', array('id'=>$defaultcategory))) {
727 mtrace(" default course category does not exist!");
729 $categories = $DB->get_records('course_categories', array(), 'sortorder', 'id', 0, 1);
730 $first = reset($categories);
731 $defaultcategory = $first->id
;
734 foreach ($createcourses as $fields) {
735 $newcourse = clone($template);
736 $newcourse->fullname
= $fields->fullname
;
737 $newcourse->shortname
= $fields->shortname
;
738 $newcourse->idnumber
= $fields->idnumber
;
739 $newcourse->category
= $fields->category ?
$fields->category
: $defaultcategory;
741 // Detect duplicate data once again, above we can not find duplicates
742 // in external data using DB collation rules...
743 if ($DB->record_exists('course', array('shortname' => $newcourse->shortname
))) {
745 mtrace(" can not insert new course, duplicate shortname detected: ".$newcourse->shortname
);
748 } else if (!empty($newcourse->idnumber
) and $DB->record_exists('course', array('idnumber' => $newcourse->idnumber
))) {
750 mtrace(" can not insert new course, duplicate idnumber detected: ".$newcourse->idnumber
);
754 $c = create_course($newcourse);
756 mtrace(" creating course: $c->id, $c->fullname, $c->shortname, $c->idnumber, $c->category");
760 unset($createcourses);
764 // close db connection
768 mtrace('...course synchronisation finished.');
774 protected function db_get_sql($table, array $conditions, array $fields, $distinct = false, $sort = "") {
775 $fields = $fields ?
implode(',', $fields) : "*";
778 foreach ($conditions as $key=>$value) {
779 $value = $this->db_encode($this->db_addslashes($value));
781 $where[] = "$key = '$value'";
784 $where = $where ?
"WHERE ".implode(" AND ", $where) : "";
785 $sort = $sort ?
"ORDER BY $sort" : "";
786 $distinct = $distinct ?
"DISTINCT" : "";
787 $sql = "SELECT $distinct $fields
796 * Tries to make connection to the external database.
798 * @return null|ADONewConnection
800 protected function db_init() {
803 require_once($CFG->libdir
.'/adodb/adodb.inc.php');
805 // Connect to the external database (forcing new connection)
806 $extdb = ADONewConnection($this->get_config('dbtype'));
807 if ($this->get_config('debugdb')) {
808 $extdb->debug
= true;
809 ob_start(); //start output buffer to allow later use of the page headers
812 // the dbtype my contain the new connection URL, so make sure we are not connected yet
813 if (!$extdb->IsConnected()) {
814 $result = $extdb->Connect($this->get_config('dbhost'), $this->get_config('dbuser'), $this->get_config('dbpass'), $this->get_config('dbname'), true);
820 $extdb->SetFetchMode(ADODB_FETCH_ASSOC
);
821 if ($this->get_config('dbsetupsql')) {
822 $extdb->Execute($this->get_config('dbsetupsql'));
827 protected function db_addslashes($text) {
828 // using custom made function for now
829 if ($this->get_config('dbsybasequoting')) {
830 $text = str_replace('\\', '\\\\', $text);
831 $text = str_replace(array('\'', '"', "\0"), array('\\\'', '\\"', '\\0'), $text);
833 $text = str_replace("'", "''", $text);
838 protected function db_encode($text) {
839 $dbenc = $this->get_config('dbencoding');
840 if (empty($dbenc) or $dbenc == 'utf-8') {
843 if (is_array($text)) {
844 foreach($text as $k=>$value) {
845 $text[$k] = $this->db_encode($value);
849 return textlib
::convert($text, 'utf-8', $dbenc);
853 protected function db_decode($text) {
854 $dbenc = $this->get_config('dbencoding');
855 if (empty($dbenc) or $dbenc == 'utf-8') {
858 if (is_array($text)) {
859 foreach($text as $k=>$value) {
860 $text[$k] = $this->db_decode($value);
864 return textlib
::convert($text, $dbenc, 'utf-8');