xref: /dokuwiki/lib/plugins/authpdo/auth.php (revision 0489c64b7de1b71fdd124114dd18525156f26327)
1f64dbc90SAndreas Gohr<?php
2*0489c64bSMoisés Braga Ribeirouse dokuwiki\Utf8\Sort;
3*0489c64bSMoisés Braga Ribeiro
4f64dbc90SAndreas Gohr/**
5f64dbc90SAndreas Gohr * DokuWiki Plugin authpdo (Auth Component)
6f64dbc90SAndreas Gohr *
7f64dbc90SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
8f64dbc90SAndreas Gohr * @author  Andreas Gohr <andi@splitbrain.org>
9f64dbc90SAndreas Gohr */
10f64dbc90SAndreas Gohr
110d586afdSAndreas Gohr/**
120d586afdSAndreas Gohr * Class auth_plugin_authpdo
130d586afdSAndreas Gohr */
143213bf4eSAndreas Gohrclass auth_plugin_authpdo extends DokuWiki_Auth_Plugin
153213bf4eSAndreas Gohr{
16f64dbc90SAndreas Gohr
17f64dbc90SAndreas Gohr    /** @var PDO */
18f64dbc90SAndreas Gohr    protected $pdo;
19f64dbc90SAndreas Gohr
200cec3e2aSAndreas Gohr    /** @var null|array The list of all groups */
210cec3e2aSAndreas Gohr    protected $groupcache = null;
220cec3e2aSAndreas Gohr
23f64dbc90SAndreas Gohr    /**
24f64dbc90SAndreas Gohr     * Constructor.
25f64dbc90SAndreas Gohr     */
263213bf4eSAndreas Gohr    public function __construct()
273213bf4eSAndreas Gohr    {
28f64dbc90SAndreas Gohr        parent::__construct(); // for compatibility
29f64dbc90SAndreas Gohr
30f64dbc90SAndreas Gohr        if (!class_exists('PDO')) {
313213bf4eSAndreas Gohr            $this->debugMsg('PDO extension for PHP not found.', -1, __LINE__);
32f64dbc90SAndreas Gohr            $this->success = false;
33f64dbc90SAndreas Gohr            return;
34f64dbc90SAndreas Gohr        }
35f64dbc90SAndreas Gohr
36f64dbc90SAndreas Gohr        if (!$this->getConf('dsn')) {
373213bf4eSAndreas Gohr            $this->debugMsg('No DSN specified', -1, __LINE__);
38f64dbc90SAndreas Gohr            $this->success = false;
39f64dbc90SAndreas Gohr            return;
40f64dbc90SAndreas Gohr        }
41f64dbc90SAndreas Gohr
42f64dbc90SAndreas Gohr        try {
43f64dbc90SAndreas Gohr            $this->pdo = new PDO(
44f64dbc90SAndreas Gohr                $this->getConf('dsn'),
45f64dbc90SAndreas Gohr                $this->getConf('user'),
460cc11d97SAndreas Gohr                conf_decodeString($this->getConf('pass')),
47f64dbc90SAndreas Gohr                array(
4870a89417SAndreas Gohr                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // always fetch as array
4970a89417SAndreas Gohr                    PDO::ATTR_EMULATE_PREPARES => true, // emulating prepares allows us to reuse param names
505de3a6a5SAndreas Gohr                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // we want exceptions, not error codes
51f64dbc90SAndreas Gohr                )
52f64dbc90SAndreas Gohr            );
53f64dbc90SAndreas Gohr        } catch (PDOException $e) {
543213bf4eSAndreas Gohr            $this->debugMsg($e);
55c27579a6SAndreas Gohr            msg($this->getLang('connectfail'), -1);
56f64dbc90SAndreas Gohr            $this->success = false;
57f64dbc90SAndreas Gohr            return;
58f64dbc90SAndreas Gohr        }
59f64dbc90SAndreas Gohr
600d586afdSAndreas Gohr        // can Users be created?
613213bf4eSAndreas Gohr        $this->cando['addUser'] = $this->checkConfig(
620d586afdSAndreas Gohr            array(
630d586afdSAndreas Gohr                'select-user',
640d586afdSAndreas Gohr                'select-user-groups',
650d586afdSAndreas Gohr                'select-groups',
660d586afdSAndreas Gohr                'insert-user',
670d586afdSAndreas Gohr                'insert-group',
680d586afdSAndreas Gohr                'join-group'
690d586afdSAndreas Gohr            )
700d586afdSAndreas Gohr        );
71f64dbc90SAndreas Gohr
720d586afdSAndreas Gohr        // can Users be deleted?
733213bf4eSAndreas Gohr        $this->cando['delUser'] = $this->checkConfig(
740d586afdSAndreas Gohr            array(
750d586afdSAndreas Gohr                'select-user',
760d586afdSAndreas Gohr                'select-user-groups',
770d586afdSAndreas Gohr                'select-groups',
787f89f089SAndreas Gohr                'leave-group',
797f89f089SAndreas Gohr                'delete-user'
800d586afdSAndreas Gohr            )
810d586afdSAndreas Gohr        );
820d586afdSAndreas Gohr
830d586afdSAndreas Gohr        // can login names be changed?
843213bf4eSAndreas Gohr        $this->cando['modLogin'] = $this->checkConfig(
850d586afdSAndreas Gohr            array(
860d586afdSAndreas Gohr                'select-user',
870d586afdSAndreas Gohr                'select-user-groups',
880d586afdSAndreas Gohr                'update-user-login'
890d586afdSAndreas Gohr            )
900d586afdSAndreas Gohr        );
910d586afdSAndreas Gohr
920d586afdSAndreas Gohr        // can passwords be changed?
933213bf4eSAndreas Gohr        $this->cando['modPass'] = $this->checkConfig(
940d586afdSAndreas Gohr            array(
950d586afdSAndreas Gohr                'select-user',
960d586afdSAndreas Gohr                'select-user-groups',
970d586afdSAndreas Gohr                'update-user-pass'
980d586afdSAndreas Gohr            )
990d586afdSAndreas Gohr        );
1000d586afdSAndreas Gohr
101ad4d5631SAndreas Gohr        // can real names be changed?
1023213bf4eSAndreas Gohr        $this->cando['modName'] = $this->checkConfig(
1030d586afdSAndreas Gohr            array(
1040d586afdSAndreas Gohr                'select-user',
1050d586afdSAndreas Gohr                'select-user-groups',
106ad4d5631SAndreas Gohr                'update-user-info:name'
107ad4d5631SAndreas Gohr            )
108ad4d5631SAndreas Gohr        );
109ad4d5631SAndreas Gohr
110ad4d5631SAndreas Gohr        // can real email be changed?
1113213bf4eSAndreas Gohr        $this->cando['modMail'] = $this->checkConfig(
112ad4d5631SAndreas Gohr            array(
113ad4d5631SAndreas Gohr                'select-user',
114ad4d5631SAndreas Gohr                'select-user-groups',
115ad4d5631SAndreas Gohr                'update-user-info:mail'
1160d586afdSAndreas Gohr            )
1170d586afdSAndreas Gohr        );
1180d586afdSAndreas Gohr
1190d586afdSAndreas Gohr        // can groups be changed?
1203213bf4eSAndreas Gohr        $this->cando['modGroups'] = $this->checkConfig(
1210d586afdSAndreas Gohr            array(
1220d586afdSAndreas Gohr                'select-user',
1230d586afdSAndreas Gohr                'select-user-groups',
1240d586afdSAndreas Gohr                'select-groups',
1250d586afdSAndreas Gohr                'leave-group',
1260d586afdSAndreas Gohr                'join-group',
1270d586afdSAndreas Gohr                'insert-group'
1280d586afdSAndreas Gohr            )
1290d586afdSAndreas Gohr        );
1300d586afdSAndreas Gohr
1310d586afdSAndreas Gohr        // can a filtered list of users be retrieved?
1323213bf4eSAndreas Gohr        $this->cando['getUsers'] = $this->checkConfig(
1330d586afdSAndreas Gohr            array(
1340d586afdSAndreas Gohr                'list-users'
1350d586afdSAndreas Gohr            )
1360d586afdSAndreas Gohr        );
1370d586afdSAndreas Gohr
1380d586afdSAndreas Gohr        // can the number of users be retrieved?
1393213bf4eSAndreas Gohr        $this->cando['getUserCount'] = $this->checkConfig(
1400d586afdSAndreas Gohr            array(
1410d586afdSAndreas Gohr                'count-users'
1420d586afdSAndreas Gohr            )
1430d586afdSAndreas Gohr        );
1440d586afdSAndreas Gohr
1450d586afdSAndreas Gohr        // can a list of available groups be retrieved?
1463213bf4eSAndreas Gohr        $this->cando['getGroups'] = $this->checkConfig(
1470d586afdSAndreas Gohr            array(
1480d586afdSAndreas Gohr                'select-groups'
1490d586afdSAndreas Gohr            )
1500d586afdSAndreas Gohr        );
1510d586afdSAndreas Gohr
152f64dbc90SAndreas Gohr        $this->success = true;
153f64dbc90SAndreas Gohr    }
154f64dbc90SAndreas Gohr
155f64dbc90SAndreas Gohr    /**
156f64dbc90SAndreas Gohr     * Check user+password
157f64dbc90SAndreas Gohr     *
158f64dbc90SAndreas Gohr     * @param string $user the user name
159f64dbc90SAndreas Gohr     * @param string $pass the clear text password
160f64dbc90SAndreas Gohr     * @return  bool
161f64dbc90SAndreas Gohr     */
1623213bf4eSAndreas Gohr    public function checkPass($user, $pass)
1633213bf4eSAndreas Gohr    {
164f64dbc90SAndreas Gohr
1653213bf4eSAndreas Gohr        $userdata = $this->selectUser($user);
166397d62a2SAndreas Gohr        if ($userdata == false) return false;
167f64dbc90SAndreas Gohr
168397d62a2SAndreas Gohr        // password checking done in SQL?
1693213bf4eSAndreas Gohr        if ($this->checkConfig(array('check-pass'))) {
170397d62a2SAndreas Gohr            $userdata['clear'] = $pass;
171397d62a2SAndreas Gohr            $userdata['hash'] = auth_cryptPassword($pass);
1723213bf4eSAndreas Gohr            $result = $this->query($this->getConf('check-pass'), $userdata);
173397d62a2SAndreas Gohr            if ($result === false) return false;
174397d62a2SAndreas Gohr            return (count($result) == 1);
175397d62a2SAndreas Gohr        }
176397d62a2SAndreas Gohr
177397d62a2SAndreas Gohr        // we do password checking on our own
178397d62a2SAndreas Gohr        if (isset($userdata['hash'])) {
179f64dbc90SAndreas Gohr            // hashed password
180c3cc6e05SAndreas Gohr            $passhash = new \dokuwiki\PassHash();
181397d62a2SAndreas Gohr            return $passhash->verify_hash($pass, $userdata['hash']);
182f64dbc90SAndreas Gohr        } else {
183f64dbc90SAndreas Gohr            // clear text password in the database O_o
184d5c0422fSAndreas Gohr            return ($pass === $userdata['clear']);
185f64dbc90SAndreas Gohr        }
186f64dbc90SAndreas Gohr    }
187f64dbc90SAndreas Gohr
188f64dbc90SAndreas Gohr    /**
189f64dbc90SAndreas Gohr     * Return user info
190f64dbc90SAndreas Gohr     *
191f64dbc90SAndreas Gohr     * Returns info about the given user needs to contain
192f64dbc90SAndreas Gohr     * at least these fields:
193f64dbc90SAndreas Gohr     *
194f64dbc90SAndreas Gohr     * name string  full name of the user
195f64dbc90SAndreas Gohr     * mail string  email addres of the user
196f64dbc90SAndreas Gohr     * grps array   list of groups the user is in
197f64dbc90SAndreas Gohr     *
198f64dbc90SAndreas Gohr     * @param string $user the user name
199f64dbc90SAndreas Gohr     * @param bool $requireGroups whether or not the returned data must include groups
200358942b5SAndreas Gohr     * @return array|bool containing user data or false
201f64dbc90SAndreas Gohr     */
2023213bf4eSAndreas Gohr    public function getUserData($user, $requireGroups = true)
2033213bf4eSAndreas Gohr    {
2043213bf4eSAndreas Gohr        $data = $this->selectUser($user);
205f64dbc90SAndreas Gohr        if ($data == false) return false;
206f64dbc90SAndreas Gohr
20770a89417SAndreas Gohr        if (isset($data['hash'])) unset($data['hash']);
20870a89417SAndreas Gohr        if (isset($data['clean'])) unset($data['clean']);
209f64dbc90SAndreas Gohr
21070a89417SAndreas Gohr        if ($requireGroups) {
2113213bf4eSAndreas Gohr            $data['grps'] = $this->selectUserGroups($data);
2125de3a6a5SAndreas Gohr            if ($data['grps'] === false) return false;
213f64dbc90SAndreas Gohr        }
214f64dbc90SAndreas Gohr
215f64dbc90SAndreas Gohr        return $data;
216f64dbc90SAndreas Gohr    }
217f64dbc90SAndreas Gohr
218f64dbc90SAndreas Gohr    /**
219f64dbc90SAndreas Gohr     * Create a new User [implement only where required/possible]
220f64dbc90SAndreas Gohr     *
221f64dbc90SAndreas Gohr     * Returns false if the user already exists, null when an error
222f64dbc90SAndreas Gohr     * occurred and true if everything went well.
223f64dbc90SAndreas Gohr     *
224f64dbc90SAndreas Gohr     * The new user HAS TO be added to the default group by this
225f64dbc90SAndreas Gohr     * function!
226f64dbc90SAndreas Gohr     *
227f64dbc90SAndreas Gohr     * Set addUser capability when implemented
228f64dbc90SAndreas Gohr     *
229f64dbc90SAndreas Gohr     * @param string $user
2305de3a6a5SAndreas Gohr     * @param string $clear
231f64dbc90SAndreas Gohr     * @param string $name
232f64dbc90SAndreas Gohr     * @param string $mail
233f64dbc90SAndreas Gohr     * @param null|array $grps
234f64dbc90SAndreas Gohr     * @return bool|null
235f64dbc90SAndreas Gohr     */
2363213bf4eSAndreas Gohr    public function createUser($user, $clear, $name, $mail, $grps = null)
2373213bf4eSAndreas Gohr    {
2385de3a6a5SAndreas Gohr        global $conf;
2395de3a6a5SAndreas Gohr
2405de3a6a5SAndreas Gohr        if (($info = $this->getUserData($user, false)) !== false) {
2415de3a6a5SAndreas Gohr            msg($this->getLang('userexists'), -1);
2425de3a6a5SAndreas Gohr            return false; // user already exists
2435de3a6a5SAndreas Gohr        }
2445de3a6a5SAndreas Gohr
2455de3a6a5SAndreas Gohr        // prepare data
2465de3a6a5SAndreas Gohr        if ($grps == null) $grps = array();
24707a11e2aSAndreas Gohr        array_unshift($grps, $conf['defaultgroup']);
2485de3a6a5SAndreas Gohr        $grps = array_unique($grps);
2495de3a6a5SAndreas Gohr        $hash = auth_cryptPassword($clear);
2505de3a6a5SAndreas Gohr        $userdata = compact('user', 'clear', 'hash', 'name', 'mail');
2515de3a6a5SAndreas Gohr
2525de3a6a5SAndreas Gohr        // action protected by transaction
2535de3a6a5SAndreas Gohr        $this->pdo->beginTransaction();
2545de3a6a5SAndreas Gohr        {
2555de3a6a5SAndreas Gohr            // insert the user
2563213bf4eSAndreas Gohr            $ok = $this->query($this->getConf('insert-user'), $userdata);
2575de3a6a5SAndreas Gohr            if ($ok === false) goto FAIL;
2585de3a6a5SAndreas Gohr            $userdata = $this->getUserData($user, false);
2595de3a6a5SAndreas Gohr            if ($userdata === false) goto FAIL;
2605de3a6a5SAndreas Gohr
2615de3a6a5SAndreas Gohr            // create all groups that do not exist, the refetch the groups
2623213bf4eSAndreas Gohr            $allgroups = $this->selectGroups();
2635de3a6a5SAndreas Gohr            foreach ($grps as $group) {
2645de3a6a5SAndreas Gohr                if (!isset($allgroups[$group])) {
2656459f496SAndreas Gohr                    $ok = $this->addGroup($group);
2665de3a6a5SAndreas Gohr                    if ($ok === false) goto FAIL;
2675de3a6a5SAndreas Gohr                }
2685de3a6a5SAndreas Gohr            }
2693213bf4eSAndreas Gohr            $allgroups = $this->selectGroups();
2705de3a6a5SAndreas Gohr
2715de3a6a5SAndreas Gohr            // add user to the groups
2725de3a6a5SAndreas Gohr            foreach ($grps as $group) {
2733213bf4eSAndreas Gohr                $ok = $this->joinGroup($userdata, $allgroups[$group]);
2745de3a6a5SAndreas Gohr                if ($ok === false) goto FAIL;
2755de3a6a5SAndreas Gohr            }
2765de3a6a5SAndreas Gohr        }
2775de3a6a5SAndreas Gohr        $this->pdo->commit();
2785de3a6a5SAndreas Gohr        return true;
2795de3a6a5SAndreas Gohr
2805de3a6a5SAndreas Gohr        // something went wrong, rollback
2815de3a6a5SAndreas Gohr        FAIL:
2825de3a6a5SAndreas Gohr        $this->pdo->rollBack();
2833213bf4eSAndreas Gohr        $this->debugMsg('Transaction rolled back', 0, __LINE__);
284c27579a6SAndreas Gohr        msg($this->getLang('writefail'), -1);
2855de3a6a5SAndreas Gohr        return null; // return error
2865de3a6a5SAndreas Gohr    }
287f64dbc90SAndreas Gohr
288f64dbc90SAndreas Gohr    /**
2894fb8dfabSAndreas Gohr     * Modify user data
290f64dbc90SAndreas Gohr     *
291f64dbc90SAndreas Gohr     * @param string $user nick of the user to be changed
292f64dbc90SAndreas Gohr     * @param array $changes array of field/value pairs to be changed (password will be clear text)
293f64dbc90SAndreas Gohr     * @return  bool
294f64dbc90SAndreas Gohr     */
2953213bf4eSAndreas Gohr    public function modifyUser($user, $changes)
2963213bf4eSAndreas Gohr    {
2974fb8dfabSAndreas Gohr        // secure everything in transaction
2984fb8dfabSAndreas Gohr        $this->pdo->beginTransaction();
2994fb8dfabSAndreas Gohr        {
3004fb8dfabSAndreas Gohr            $olddata = $this->getUserData($user);
3014fb8dfabSAndreas Gohr            $oldgroups = $olddata['grps'];
3024fb8dfabSAndreas Gohr            unset($olddata['grps']);
3034fb8dfabSAndreas Gohr
3044fb8dfabSAndreas Gohr            // changing the user name?
3054fb8dfabSAndreas Gohr            if (isset($changes['user'])) {
3064fb8dfabSAndreas Gohr                if ($this->getUserData($changes['user'], false)) goto FAIL;
3074fb8dfabSAndreas Gohr                $params = $olddata;
3084fb8dfabSAndreas Gohr                $params['newlogin'] = $changes['user'];
3094fb8dfabSAndreas Gohr
3103213bf4eSAndreas Gohr                $ok = $this->query($this->getConf('update-user-login'), $params);
3114fb8dfabSAndreas Gohr                if ($ok === false) goto FAIL;
3124fb8dfabSAndreas Gohr            }
3134fb8dfabSAndreas Gohr
3144fb8dfabSAndreas Gohr            // changing the password?
3154fb8dfabSAndreas Gohr            if (isset($changes['pass'])) {
3164fb8dfabSAndreas Gohr                $params = $olddata;
3174fb8dfabSAndreas Gohr                $params['clear'] = $changes['pass'];
3184fb8dfabSAndreas Gohr                $params['hash'] = auth_cryptPassword($changes['pass']);
3194fb8dfabSAndreas Gohr
3203213bf4eSAndreas Gohr                $ok = $this->query($this->getConf('update-user-pass'), $params);
3214fb8dfabSAndreas Gohr                if ($ok === false) goto FAIL;
3224fb8dfabSAndreas Gohr            }
3234fb8dfabSAndreas Gohr
3244fb8dfabSAndreas Gohr            // changing info?
3254fb8dfabSAndreas Gohr            if (isset($changes['mail']) || isset($changes['name'])) {
3264fb8dfabSAndreas Gohr                $params = $olddata;
3274fb8dfabSAndreas Gohr                if (isset($changes['mail'])) $params['mail'] = $changes['mail'];
3284fb8dfabSAndreas Gohr                if (isset($changes['name'])) $params['name'] = $changes['name'];
3294fb8dfabSAndreas Gohr
3303213bf4eSAndreas Gohr                $ok = $this->query($this->getConf('update-user-info'), $params);
3314fb8dfabSAndreas Gohr                if ($ok === false) goto FAIL;
3324fb8dfabSAndreas Gohr            }
3334fb8dfabSAndreas Gohr
3344fb8dfabSAndreas Gohr            // changing groups?
3354fb8dfabSAndreas Gohr            if (isset($changes['grps'])) {
3363213bf4eSAndreas Gohr                $allgroups = $this->selectGroups();
3374fb8dfabSAndreas Gohr
3384fb8dfabSAndreas Gohr                // remove membership for previous groups
3394fb8dfabSAndreas Gohr                foreach ($oldgroups as $group) {
340358942b5SAndreas Gohr                    if (!in_array($group, $changes['grps']) && isset($allgroups[$group])) {
3413213bf4eSAndreas Gohr                        $ok = $this->leaveGroup($olddata, $allgroups[$group]);
3424fb8dfabSAndreas Gohr                        if ($ok === false) goto FAIL;
3434fb8dfabSAndreas Gohr                    }
3444fb8dfabSAndreas Gohr                }
3454fb8dfabSAndreas Gohr
3464fb8dfabSAndreas Gohr                // create all new groups that are missing
3474fb8dfabSAndreas Gohr                $added = 0;
3484fb8dfabSAndreas Gohr                foreach ($changes['grps'] as $group) {
3494fb8dfabSAndreas Gohr                    if (!isset($allgroups[$group])) {
3506459f496SAndreas Gohr                        $ok = $this->addGroup($group);
3514fb8dfabSAndreas Gohr                        if ($ok === false) goto FAIL;
3524fb8dfabSAndreas Gohr                        $added++;
3534fb8dfabSAndreas Gohr                    }
3544fb8dfabSAndreas Gohr                }
3554fb8dfabSAndreas Gohr                // reload group info
3563213bf4eSAndreas Gohr                if ($added > 0) $allgroups = $this->selectGroups();
3574fb8dfabSAndreas Gohr
3584fb8dfabSAndreas Gohr                // add membership for new groups
3594fb8dfabSAndreas Gohr                foreach ($changes['grps'] as $group) {
3604fb8dfabSAndreas Gohr                    if (!in_array($group, $oldgroups)) {
3613213bf4eSAndreas Gohr                        $ok = $this->joinGroup($olddata, $allgroups[$group]);
3624fb8dfabSAndreas Gohr                        if ($ok === false) goto FAIL;
3634fb8dfabSAndreas Gohr                    }
3644fb8dfabSAndreas Gohr                }
3654fb8dfabSAndreas Gohr            }
3664fb8dfabSAndreas Gohr
3674fb8dfabSAndreas Gohr        }
3684fb8dfabSAndreas Gohr        $this->pdo->commit();
3694fb8dfabSAndreas Gohr        return true;
3704fb8dfabSAndreas Gohr
3714fb8dfabSAndreas Gohr        // something went wrong, rollback
3724fb8dfabSAndreas Gohr        FAIL:
3734fb8dfabSAndreas Gohr        $this->pdo->rollBack();
3743213bf4eSAndreas Gohr        $this->debugMsg('Transaction rolled back', 0, __LINE__);
375c27579a6SAndreas Gohr        msg($this->getLang('writefail'), -1);
3764fb8dfabSAndreas Gohr        return false; // return error
3774fb8dfabSAndreas Gohr    }
378f64dbc90SAndreas Gohr
379f64dbc90SAndreas Gohr    /**
380e19be516SAndreas Gohr     * Delete one or more users
381f64dbc90SAndreas Gohr     *
382f64dbc90SAndreas Gohr     * Set delUser capability when implemented
383f64dbc90SAndreas Gohr     *
384f64dbc90SAndreas Gohr     * @param array $users
385f64dbc90SAndreas Gohr     * @return  int    number of users deleted
386f64dbc90SAndreas Gohr     */
3873213bf4eSAndreas Gohr    public function deleteUsers($users)
3883213bf4eSAndreas Gohr    {
389e19be516SAndreas Gohr        $count = 0;
390e19be516SAndreas Gohr        foreach ($users as $user) {
3913213bf4eSAndreas Gohr            if ($this->deleteUser($user)) $count++;
392e19be516SAndreas Gohr        }
393e19be516SAndreas Gohr        return $count;
394e19be516SAndreas Gohr    }
395f64dbc90SAndreas Gohr
396f64dbc90SAndreas Gohr    /**
397f64dbc90SAndreas Gohr     * Bulk retrieval of user data [implement only where required/possible]
398f64dbc90SAndreas Gohr     *
399f64dbc90SAndreas Gohr     * Set getUsers capability when implemented
400f64dbc90SAndreas Gohr     *
401f64dbc90SAndreas Gohr     * @param int $start index of first user to be returned
402f64dbc90SAndreas Gohr     * @param int $limit max number of users to be returned
403f64dbc90SAndreas Gohr     * @param array $filter array of field/pattern pairs, null for no filter
404f64dbc90SAndreas Gohr     * @return  array list of userinfo (refer getUserData for internal userinfo details)
405f64dbc90SAndreas Gohr     */
4063213bf4eSAndreas Gohr    public function retrieveUsers($start = 0, $limit = -1, $filter = null)
4073213bf4eSAndreas Gohr    {
4086459f496SAndreas Gohr        if ($limit < 0) $limit = 10000; // we don't support no limit
4096459f496SAndreas Gohr        if (is_null($filter)) $filter = array();
4106459f496SAndreas Gohr
41112c7f5c3SAndreas Gohr        if (isset($filter['grps'])) $filter['group'] = $filter['grps'];
4126459f496SAndreas Gohr        foreach (array('user', 'name', 'mail', 'group') as $key) {
4136459f496SAndreas Gohr            if (!isset($filter[$key])) {
4146459f496SAndreas Gohr                $filter[$key] = '%';
4156459f496SAndreas Gohr            } else {
4166459f496SAndreas Gohr                $filter[$key] = '%' . $filter[$key] . '%';
4176459f496SAndreas Gohr            }
4186459f496SAndreas Gohr        }
41914119d44SAndreas Gohr        $filter['start'] = (int)$start;
42014119d44SAndreas Gohr        $filter['end'] = (int)$start + $limit;
42114119d44SAndreas Gohr        $filter['limit'] = (int)$limit;
4226459f496SAndreas Gohr
4233213bf4eSAndreas Gohr        $result = $this->query($this->getConf('list-users'), $filter);
4246459f496SAndreas Gohr        if (!$result) return array();
4256459f496SAndreas Gohr        $users = array();
42688ca2487SPhy        if (is_array($result)) {
4276459f496SAndreas Gohr            foreach ($result as $row) {
4286459f496SAndreas Gohr                if (!isset($row['user'])) {
42931a58abaSAndreas Gohr                    $this->debugMsg("list-users statement did not return 'user' attribute", -1, __LINE__);
4306459f496SAndreas Gohr                    return array();
4316459f496SAndreas Gohr                }
4323e2a8145SAndreas Gohr                $users[] = $this->getUserData($row['user']);
4336459f496SAndreas Gohr            }
43488ca2487SPhy        } else {
43531a58abaSAndreas Gohr            $this->debugMsg("list-users statement did not return a list of result", -1, __LINE__);
43688ca2487SPhy        }
4376459f496SAndreas Gohr        return $users;
4386459f496SAndreas Gohr    }
439f64dbc90SAndreas Gohr
440f64dbc90SAndreas Gohr    /**
441f64dbc90SAndreas Gohr     * Return a count of the number of user which meet $filter criteria
442f64dbc90SAndreas Gohr     *
443f64dbc90SAndreas Gohr     * @param array $filter array of field/pattern pairs, empty array for no filter
444f64dbc90SAndreas Gohr     * @return int
445f64dbc90SAndreas Gohr     */
4463213bf4eSAndreas Gohr    public function getUserCount($filter = array())
4473213bf4eSAndreas Gohr    {
4486459f496SAndreas Gohr        if (is_null($filter)) $filter = array();
4496459f496SAndreas Gohr
45012c7f5c3SAndreas Gohr        if (isset($filter['grps'])) $filter['group'] = $filter['grps'];
4516459f496SAndreas Gohr        foreach (array('user', 'name', 'mail', 'group') as $key) {
4526459f496SAndreas Gohr            if (!isset($filter[$key])) {
4536459f496SAndreas Gohr                $filter[$key] = '%';
4546459f496SAndreas Gohr            } else {
4556459f496SAndreas Gohr                $filter[$key] = '%' . $filter[$key] . '%';
4566459f496SAndreas Gohr            }
4576459f496SAndreas Gohr        }
4586459f496SAndreas Gohr
4593213bf4eSAndreas Gohr        $result = $this->query($this->getConf('count-users'), $filter);
4606459f496SAndreas Gohr        if (!$result || !isset($result[0]['count'])) {
4613213bf4eSAndreas Gohr            $this->debugMsg("Statement did not return 'count' attribute", -1, __LINE__);
4626459f496SAndreas Gohr        }
463f3c1c207SAndreas Gohr        return (int)$result[0]['count'];
4646459f496SAndreas Gohr    }
465f64dbc90SAndreas Gohr
466f64dbc90SAndreas Gohr    /**
4676459f496SAndreas Gohr     * Create a new group with the given name
468f64dbc90SAndreas Gohr     *
469f64dbc90SAndreas Gohr     * @param string $group
470f64dbc90SAndreas Gohr     * @return bool
471f64dbc90SAndreas Gohr     */
4723213bf4eSAndreas Gohr    public function addGroup($group)
4733213bf4eSAndreas Gohr    {
4746459f496SAndreas Gohr        $sql = $this->getConf('insert-group');
4756459f496SAndreas Gohr
4763213bf4eSAndreas Gohr        $result = $this->query($sql, array(':group' => $group));
4773213bf4eSAndreas Gohr        $this->clearGroupCache();
4786459f496SAndreas Gohr        if ($result === false) return false;
4796459f496SAndreas Gohr        return true;
4806459f496SAndreas Gohr    }
481f64dbc90SAndreas Gohr
482f64dbc90SAndreas Gohr    /**
4835de3a6a5SAndreas Gohr     * Retrieve groups
484f64dbc90SAndreas Gohr     *
485f64dbc90SAndreas Gohr     * Set getGroups capability when implemented
486f64dbc90SAndreas Gohr     *
487f64dbc90SAndreas Gohr     * @param int $start
488f64dbc90SAndreas Gohr     * @param int $limit
489f64dbc90SAndreas Gohr     * @return  array
490f64dbc90SAndreas Gohr     */
4913213bf4eSAndreas Gohr    public function retrieveGroups($start = 0, $limit = 0)
4923213bf4eSAndreas Gohr    {
4933213bf4eSAndreas Gohr        $groups = array_keys($this->selectGroups());
4945de3a6a5SAndreas Gohr        if ($groups === false) return array();
495f64dbc90SAndreas Gohr
4965de3a6a5SAndreas Gohr        if (!$limit) {
4975de3a6a5SAndreas Gohr            return array_splice($groups, $start);
4985de3a6a5SAndreas Gohr        } else {
4995de3a6a5SAndreas Gohr            return array_splice($groups, $start, $limit);
500f64dbc90SAndreas Gohr        }
501f64dbc90SAndreas Gohr    }
502f64dbc90SAndreas Gohr
503f64dbc90SAndreas Gohr    /**
504f64dbc90SAndreas Gohr     * Select data of a specified user
505f64dbc90SAndreas Gohr     *
5065de3a6a5SAndreas Gohr     * @param string $user the user name
5075de3a6a5SAndreas Gohr     * @return bool|array user data, false on error
508f64dbc90SAndreas Gohr     */
5093213bf4eSAndreas Gohr    protected function selectUser($user)
5103213bf4eSAndreas Gohr    {
511f64dbc90SAndreas Gohr        $sql = $this->getConf('select-user');
512f64dbc90SAndreas Gohr
5133213bf4eSAndreas Gohr        $result = $this->query($sql, array(':user' => $user));
51470a89417SAndreas Gohr        if (!$result) return false;
515f64dbc90SAndreas Gohr
51670a89417SAndreas Gohr        if (count($result) > 1) {
5173213bf4eSAndreas Gohr            $this->debugMsg('Found more than one matching user', -1, __LINE__);
518f64dbc90SAndreas Gohr            return false;
519f64dbc90SAndreas Gohr        }
520f64dbc90SAndreas Gohr
521f64dbc90SAndreas Gohr        $data = array_shift($result);
522f64dbc90SAndreas Gohr        $dataok = true;
523f64dbc90SAndreas Gohr
524f64dbc90SAndreas Gohr        if (!isset($data['user'])) {
5253213bf4eSAndreas Gohr            $this->debugMsg("Statement did not return 'user' attribute", -1, __LINE__);
526f64dbc90SAndreas Gohr            $dataok = false;
527f64dbc90SAndreas Gohr        }
5283213bf4eSAndreas Gohr        if (!isset($data['hash']) && !isset($data['clear']) && !$this->checkConfig(array('check-pass'))) {
5293213bf4eSAndreas Gohr            $this->debugMsg("Statement did not return 'clear' or 'hash' attribute", -1, __LINE__);
530f64dbc90SAndreas Gohr            $dataok = false;
531f64dbc90SAndreas Gohr        }
532f64dbc90SAndreas Gohr        if (!isset($data['name'])) {
5333213bf4eSAndreas Gohr            $this->debugMsg("Statement did not return 'name' attribute", -1, __LINE__);
534f64dbc90SAndreas Gohr            $dataok = false;
535f64dbc90SAndreas Gohr        }
536f64dbc90SAndreas Gohr        if (!isset($data['mail'])) {
5373213bf4eSAndreas Gohr            $this->debugMsg("Statement did not return 'mail' attribute", -1, __LINE__);
538f64dbc90SAndreas Gohr            $dataok = false;
539f64dbc90SAndreas Gohr        }
540f64dbc90SAndreas Gohr
541f64dbc90SAndreas Gohr        if (!$dataok) return false;
542f64dbc90SAndreas Gohr        return $data;
543f64dbc90SAndreas Gohr    }
544f64dbc90SAndreas Gohr
545f64dbc90SAndreas Gohr    /**
546e19be516SAndreas Gohr     * Delete a user after removing all their group memberships
547e19be516SAndreas Gohr     *
548e19be516SAndreas Gohr     * @param string $user
549e19be516SAndreas Gohr     * @return bool true when the user was deleted
550e19be516SAndreas Gohr     */
5513213bf4eSAndreas Gohr    protected function deleteUser($user)
5523213bf4eSAndreas Gohr    {
553e19be516SAndreas Gohr        $this->pdo->beginTransaction();
554e19be516SAndreas Gohr        {
555e19be516SAndreas Gohr            $userdata = $this->getUserData($user);
556e19be516SAndreas Gohr            if ($userdata === false) goto FAIL;
5573213bf4eSAndreas Gohr            $allgroups = $this->selectGroups();
558e19be516SAndreas Gohr
559e19be516SAndreas Gohr            // remove group memberships (ignore errors)
560e19be516SAndreas Gohr            foreach ($userdata['grps'] as $group) {
561358942b5SAndreas Gohr                if (isset($allgroups[$group])) {
5623213bf4eSAndreas Gohr                    $this->leaveGroup($userdata, $allgroups[$group]);
563e19be516SAndreas Gohr                }
564358942b5SAndreas Gohr            }
565e19be516SAndreas Gohr
5663213bf4eSAndreas Gohr            $ok = $this->query($this->getConf('delete-user'), $userdata);
567e19be516SAndreas Gohr            if ($ok === false) goto FAIL;
568e19be516SAndreas Gohr        }
569e19be516SAndreas Gohr        $this->pdo->commit();
570e19be516SAndreas Gohr        return true;
571e19be516SAndreas Gohr
572e19be516SAndreas Gohr        FAIL:
573e19be516SAndreas Gohr        $this->pdo->rollBack();
574e19be516SAndreas Gohr        return false;
575e19be516SAndreas Gohr    }
576e19be516SAndreas Gohr
577e19be516SAndreas Gohr    /**
57870a89417SAndreas Gohr     * Select all groups of a user
57970a89417SAndreas Gohr     *
58070a89417SAndreas Gohr     * @param array $userdata The userdata as returned by _selectUser()
5815de3a6a5SAndreas Gohr     * @return array|bool list of group names, false on error
58270a89417SAndreas Gohr     */
5833213bf4eSAndreas Gohr    protected function selectUserGroups($userdata)
5843213bf4eSAndreas Gohr    {
58570a89417SAndreas Gohr        global $conf;
58670a89417SAndreas Gohr        $sql = $this->getConf('select-user-groups');
5873213bf4eSAndreas Gohr        $result = $this->query($sql, $userdata);
5885de3a6a5SAndreas Gohr        if ($result === false) return false;
58970a89417SAndreas Gohr
59070a89417SAndreas Gohr        $groups = array($conf['defaultgroup']); // always add default config
59188ca2487SPhy        if (is_array($result)) {
5925de3a6a5SAndreas Gohr            foreach ($result as $row) {
5935de3a6a5SAndreas Gohr                if (!isset($row['group'])) {
59431a58abaSAndreas Gohr                    $this->debugMsg("No 'group' field returned in select-user-groups statement", -1, __LINE__);
5955de3a6a5SAndreas Gohr                    return false;
5965de3a6a5SAndreas Gohr                }
59770a89417SAndreas Gohr                $groups[] = $row['group'];
59870a89417SAndreas Gohr            }
59988ca2487SPhy        } else {
60031a58abaSAndreas Gohr            $this->debugMsg("select-user-groups statement did not return a list of result", -1, __LINE__);
60188ca2487SPhy        }
60270a89417SAndreas Gohr
60370a89417SAndreas Gohr        $groups = array_unique($groups);
604*0489c64bSMoisés Braga Ribeiro        Sort::sort($groups);
60570a89417SAndreas Gohr        return $groups;
60670a89417SAndreas Gohr    }
60770a89417SAndreas Gohr
60870a89417SAndreas Gohr    /**
6095de3a6a5SAndreas Gohr     * Select all available groups
6105de3a6a5SAndreas Gohr     *
6115de3a6a5SAndreas Gohr     * @return array|bool list of all available groups and their properties
6125de3a6a5SAndreas Gohr     */
6133213bf4eSAndreas Gohr    protected function selectGroups()
6143213bf4eSAndreas Gohr    {
6150cec3e2aSAndreas Gohr        if ($this->groupcache) return $this->groupcache;
6160cec3e2aSAndreas Gohr
6175de3a6a5SAndreas Gohr        $sql = $this->getConf('select-groups');
6183213bf4eSAndreas Gohr        $result = $this->query($sql);
6195de3a6a5SAndreas Gohr        if ($result === false) return false;
6205de3a6a5SAndreas Gohr
6215de3a6a5SAndreas Gohr        $groups = array();
62288ca2487SPhy        if (is_array($result)) {
6235de3a6a5SAndreas Gohr            foreach ($result as $row) {
6245de3a6a5SAndreas Gohr                if (!isset($row['group'])) {
6253213bf4eSAndreas Gohr                    $this->debugMsg("No 'group' field returned from select-groups statement", -1, __LINE__);
6265de3a6a5SAndreas Gohr                    return false;
6275de3a6a5SAndreas Gohr                }
6285de3a6a5SAndreas Gohr
6295de3a6a5SAndreas Gohr                // relayout result with group name as key
6305de3a6a5SAndreas Gohr                $group = $row['group'];
6315de3a6a5SAndreas Gohr                $groups[$group] = $row;
6325de3a6a5SAndreas Gohr            }
63388ca2487SPhy        } else {
63431a58abaSAndreas Gohr            $this->debugMsg("select-groups statement did not return a list of result", -1, __LINE__);
63588ca2487SPhy        }
6365de3a6a5SAndreas Gohr
637*0489c64bSMoisés Braga Ribeiro        Sort::ksort($groups);
6385de3a6a5SAndreas Gohr        return $groups;
6395de3a6a5SAndreas Gohr    }
6405de3a6a5SAndreas Gohr
6415de3a6a5SAndreas Gohr    /**
6420cec3e2aSAndreas Gohr     * Remove all entries from the group cache
6430cec3e2aSAndreas Gohr     */
6443213bf4eSAndreas Gohr    protected function clearGroupCache()
6453213bf4eSAndreas Gohr    {
6460cec3e2aSAndreas Gohr        $this->groupcache = null;
6470cec3e2aSAndreas Gohr    }
6480cec3e2aSAndreas Gohr
6490cec3e2aSAndreas Gohr    /**
6504fb8dfabSAndreas Gohr     * Adds the user to the group
6515de3a6a5SAndreas Gohr     *
6525de3a6a5SAndreas Gohr     * @param array $userdata all the user data
6535de3a6a5SAndreas Gohr     * @param array $groupdata all the group data
6545de3a6a5SAndreas Gohr     * @return bool
6555de3a6a5SAndreas Gohr     */
6563213bf4eSAndreas Gohr    protected function joinGroup($userdata, $groupdata)
6573213bf4eSAndreas Gohr    {
6585de3a6a5SAndreas Gohr        $data = array_merge($userdata, $groupdata);
6595de3a6a5SAndreas Gohr        $sql = $this->getConf('join-group');
6603213bf4eSAndreas Gohr        $result = $this->query($sql, $data);
6615de3a6a5SAndreas Gohr        if ($result === false) return false;
6625de3a6a5SAndreas Gohr        return true;
6635de3a6a5SAndreas Gohr    }
6645de3a6a5SAndreas Gohr
6655de3a6a5SAndreas Gohr    /**
6664fb8dfabSAndreas Gohr     * Removes the user from the group
6674fb8dfabSAndreas Gohr     *
6684fb8dfabSAndreas Gohr     * @param array $userdata all the user data
6694fb8dfabSAndreas Gohr     * @param array $groupdata all the group data
6704fb8dfabSAndreas Gohr     * @return bool
6714fb8dfabSAndreas Gohr     */
6723213bf4eSAndreas Gohr    protected function leaveGroup($userdata, $groupdata)
6733213bf4eSAndreas Gohr    {
6744fb8dfabSAndreas Gohr        $data = array_merge($userdata, $groupdata);
6754fb8dfabSAndreas Gohr        $sql = $this->getConf('leave-group');
6763213bf4eSAndreas Gohr        $result = $this->query($sql, $data);
6774fb8dfabSAndreas Gohr        if ($result === false) return false;
6784fb8dfabSAndreas Gohr        return true;
6794fb8dfabSAndreas Gohr    }
6804fb8dfabSAndreas Gohr
6814fb8dfabSAndreas Gohr    /**
68270a89417SAndreas Gohr     * Executes a query
68370a89417SAndreas Gohr     *
68470a89417SAndreas Gohr     * @param string $sql The SQL statement to execute
68570a89417SAndreas Gohr     * @param array $arguments Named parameters to be used in the statement
686f695c447SAndreas Gohr     * @return array|int|bool The result as associative array for SELECTs, affected rows for others, false on error
68770a89417SAndreas Gohr     */
6883213bf4eSAndreas Gohr    protected function query($sql, $arguments = array())
6893213bf4eSAndreas Gohr    {
690f695c447SAndreas Gohr        $sql = trim($sql);
6915de3a6a5SAndreas Gohr        if (empty($sql)) {
6923213bf4eSAndreas Gohr            $this->debugMsg('No SQL query given', -1, __LINE__);
6935de3a6a5SAndreas Gohr            return false;
6945de3a6a5SAndreas Gohr        }
6955de3a6a5SAndreas Gohr
69614119d44SAndreas Gohr        // execute
69770a89417SAndreas Gohr        $params = array();
69814119d44SAndreas Gohr        $sth = $this->pdo->prepare($sql);
69988ca2487SPhy        $result = false;
70014119d44SAndreas Gohr        try {
70114119d44SAndreas Gohr            // prepare parameters - we only use those that exist in the SQL
70270a89417SAndreas Gohr            foreach ($arguments as $key => $value) {
70370a89417SAndreas Gohr                if (is_array($value)) continue;
70470a89417SAndreas Gohr                if (is_object($value)) continue;
70570a89417SAndreas Gohr                if ($key[0] != ':') $key = ":$key"; // prefix with colon if needed
70614119d44SAndreas Gohr                if (strpos($sql, $key) === false) continue; // skip if parameter is missing
70714119d44SAndreas Gohr
70814119d44SAndreas Gohr                if (is_int($value)) {
70914119d44SAndreas Gohr                    $sth->bindValue($key, $value, PDO::PARAM_INT);
71014119d44SAndreas Gohr                } else {
71114119d44SAndreas Gohr                    $sth->bindValue($key, $value);
71214119d44SAndreas Gohr                }
713f6cd8a7fSphjanderson                $params[$key] = $value; //remember for debugging
71470a89417SAndreas Gohr            }
71570a89417SAndreas Gohr
71614119d44SAndreas Gohr            $sth->execute();
7176a1b9bfeSPhy            // only report last line's result
7186a1b9bfeSPhy            $hasnextrowset = true;
7196a1b9bfeSPhy            $currentsql = $sql;
7206a1b9bfeSPhy            while ($hasnextrowset) {
7216a1b9bfeSPhy                if (strtolower(substr($currentsql, 0, 6)) == 'select') {
72270a89417SAndreas Gohr                    $result = $sth->fetchAll();
723f695c447SAndreas Gohr                } else {
724f695c447SAndreas Gohr                    $result = $sth->rowCount();
725f695c447SAndreas Gohr                }
7266a1b9bfeSPhy                $semi_pos = strpos($currentsql, ';');
7276a1b9bfeSPhy                if ($semi_pos) {
7286a1b9bfeSPhy                    $currentsql = trim(substr($currentsql, $semi_pos + 1));
7296a1b9bfeSPhy                }
7306a1b9bfeSPhy                try {
7316a1b9bfeSPhy                    $hasnextrowset = $sth->nextRowset(); // run next rowset
7326a1b9bfeSPhy                } catch (PDOException $rowset_e) {
7336a1b9bfeSPhy                    $hasnextrowset = false; // driver does not support multi-rowset, should be executed in one time
7346a1b9bfeSPhy                }
7356a1b9bfeSPhy            }
7365de3a6a5SAndreas Gohr        } catch (Exception $e) {
7374fb8dfabSAndreas Gohr            // report the caller's line
7384fb8dfabSAndreas Gohr            $trace = debug_backtrace();
7394fb8dfabSAndreas Gohr            $line = $trace[0]['line'];
7403213bf4eSAndreas Gohr            $dsql = $this->debugSQL($sql, $params, !defined('DOKU_UNITTEST'));
7413213bf4eSAndreas Gohr            $this->debugMsg($e, -1, $line);
7423213bf4eSAndreas Gohr            $this->debugMsg("SQL: <pre>$dsql</pre>", -1, $line);
7431600c7ccSAndreas Gohr        }
74470a89417SAndreas Gohr        $sth->closeCursor();
74570a89417SAndreas Gohr        $sth = null;
74670a89417SAndreas Gohr
7475de3a6a5SAndreas Gohr        return $result;
7485de3a6a5SAndreas Gohr    }
74970a89417SAndreas Gohr
75070a89417SAndreas Gohr    /**
751f64dbc90SAndreas Gohr     * Wrapper around msg() but outputs only when debug is enabled
752f64dbc90SAndreas Gohr     *
753f64dbc90SAndreas Gohr     * @param string|Exception $message
754f64dbc90SAndreas Gohr     * @param int $err
755f64dbc90SAndreas Gohr     * @param int $line
756f64dbc90SAndreas Gohr     */
7573213bf4eSAndreas Gohr    protected function debugMsg($message, $err = 0, $line = 0)
7583213bf4eSAndreas Gohr    {
759f64dbc90SAndreas Gohr        if (!$this->getConf('debug')) return;
760f64dbc90SAndreas Gohr        if (is_a($message, 'Exception')) {
761f64dbc90SAndreas Gohr            $err = -1;
762f64dbc90SAndreas Gohr            $msg = $message->getMessage();
7634fb8dfabSAndreas Gohr            if (!$line) $line = $message->getLine();
764f64dbc90SAndreas Gohr        } else {
765f64dbc90SAndreas Gohr            $msg = $message;
766f64dbc90SAndreas Gohr        }
767f64dbc90SAndreas Gohr
768f64dbc90SAndreas Gohr        if (defined('DOKU_UNITTEST')) {
769f64dbc90SAndreas Gohr            printf("\n%s, %s:%d\n", $msg, __FILE__, $line);
770f64dbc90SAndreas Gohr        } else {
771f64dbc90SAndreas Gohr            msg('authpdo: ' . $msg, $err, $line, __FILE__);
772f64dbc90SAndreas Gohr        }
773f64dbc90SAndreas Gohr    }
7745de3a6a5SAndreas Gohr
7755de3a6a5SAndreas Gohr    /**
7765de3a6a5SAndreas Gohr     * Check if the given config strings are set
7775de3a6a5SAndreas Gohr     *
7785de3a6a5SAndreas Gohr     * @param string[] $keys
7795de3a6a5SAndreas Gohr     * @return  bool
78031a58abaSAndreas Gohr     * @author  Matthias Grimm <matthiasgrimm@users.sourceforge.net>
78131a58abaSAndreas Gohr     *
7825de3a6a5SAndreas Gohr     */
7833213bf4eSAndreas Gohr    protected function checkConfig($keys)
7843213bf4eSAndreas Gohr    {
7855de3a6a5SAndreas Gohr        foreach ($keys as $key) {
786ad4d5631SAndreas Gohr            $params = explode(':', $key);
787ad4d5631SAndreas Gohr            $key = array_shift($params);
788ad4d5631SAndreas Gohr            $sql = trim($this->getConf($key));
789ad4d5631SAndreas Gohr
790ad4d5631SAndreas Gohr            // check if sql is set
791ad4d5631SAndreas Gohr            if (!$sql) return false;
792ad4d5631SAndreas Gohr            // check if needed params are there
793ad4d5631SAndreas Gohr            foreach ($params as $param) {
794ad4d5631SAndreas Gohr                if (strpos($sql, ":$param") === false) return false;
795ad4d5631SAndreas Gohr            }
7965de3a6a5SAndreas Gohr        }
7975de3a6a5SAndreas Gohr
7985de3a6a5SAndreas Gohr        return true;
7995de3a6a5SAndreas Gohr    }
8005de3a6a5SAndreas Gohr
8015de3a6a5SAndreas Gohr    /**
8025de3a6a5SAndreas Gohr     * create an approximation of the SQL string with parameters replaced
8035de3a6a5SAndreas Gohr     *
8045de3a6a5SAndreas Gohr     * @param string $sql
8055de3a6a5SAndreas Gohr     * @param array $params
8065de3a6a5SAndreas Gohr     * @param bool $htmlescape Should the result be escaped for output in HTML?
8075de3a6a5SAndreas Gohr     * @return string
8085de3a6a5SAndreas Gohr     */
8093213bf4eSAndreas Gohr    protected function debugSQL($sql, $params, $htmlescape = true)
8103213bf4eSAndreas Gohr    {
8115de3a6a5SAndreas Gohr        foreach ($params as $key => $val) {
8125de3a6a5SAndreas Gohr            if (is_int($val)) {
8135de3a6a5SAndreas Gohr                $val = $this->pdo->quote($val, PDO::PARAM_INT);
8145de3a6a5SAndreas Gohr            } elseif (is_bool($val)) {
8155de3a6a5SAndreas Gohr                $val = $this->pdo->quote($val, PDO::PARAM_BOOL);
8165de3a6a5SAndreas Gohr            } elseif (is_null($val)) {
8175de3a6a5SAndreas Gohr                $val = 'NULL';
8185de3a6a5SAndreas Gohr            } else {
8195de3a6a5SAndreas Gohr                $val = $this->pdo->quote($val);
8205de3a6a5SAndreas Gohr            }
8215de3a6a5SAndreas Gohr            $sql = str_replace($key, $val, $sql);
8225de3a6a5SAndreas Gohr        }
8235de3a6a5SAndreas Gohr        if ($htmlescape) $sql = hsc($sql);
8245de3a6a5SAndreas Gohr        return $sql;
8255de3a6a5SAndreas Gohr    }
826f64dbc90SAndreas Gohr}
827f64dbc90SAndreas Gohr
828f64dbc90SAndreas Gohr// vim:ts=4:sw=4:et:
829