1<?php
2
3use dokuwiki\ErrorHandler;
4use dokuwiki\Extension\Plugin;
5use dokuwiki\plugin\sqlite\SQLiteDB;
6
7/**
8 * DokuWiki Plugin questionnaire (Helper Component)
9 *
10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 * @author Andreas Gohr <dokuwiki@cosmocode.de>
12 */
13class helper_plugin_questionnaire extends Plugin
14{
15    protected $db;
16
17    /**
18     * Get SQLiteDB instance
19     *
20     * @return SQLiteDB|null
21     */
22    public function getDB()
23    {
24        if ($this->db === null) {
25            try {
26                $this->db = new SQLiteDB('questionnaire', DOKU_PLUGIN . 'questionnaire/db/');
27                $this->db->getPdo()->exec('PRAGMA foreign_keys = ON');
28            } catch (\Exception $exception) {
29                if (defined('DOKU_UNITTEST')) throw new \RuntimeException('Could not load SQLite', 0, $exception);
30                ErrorHandler::logException($exception);
31                msg($this->getLang('nosqlite'), -1);
32                return null;
33            }
34        }
35        return $this->db;
36    }
37
38    /**
39     * Get the questionnaire meta data
40     *
41     * @param string $page The page to get the questionnaire for
42     * @return array|null Null if the questionnaire has not been enabled yet
43     */
44    public function getQuestionnaire($page)
45    {
46        $db = $this->getDB();
47        if (!$db) return null;
48
49        $sql = 'SELECT * FROM questionnaires WHERE page = ?';
50        return $db->queryRecord($sql, $page);
51    }
52
53    /**
54     * Activate the questionnaire for a page
55     *
56     * @param string $page The page to enable the questionnaire for
57     * @param string $user The user enabling the questionnaire
58     * @throws Exception if the questionnaire is already enabled
59     */
60    public function activateQuestionnaire($page, $user)
61    {
62        $db = $this->getDB();
63
64        $record = [
65            'page' => $page,
66            'activated_on' => time(),
67            'activated_by' => $user,
68            'deactivated_on' => 0,
69            'deactivated_by' => '',
70        ];
71
72        $db->saveRecord('questionnaires', $record);
73    }
74
75    /**
76     * Deactivate the questionnaire for a page
77     *
78     * @param string $page The page to disable the questionnaire for
79     * @param string $user The user disabling the questionnaire
80     * @throws Exception if the questionnaire is not enabled
81     */
82    public function deactivateQuestionnaire($page, $user)
83    {
84        $db = $this->getDB();
85
86        $record = $db->queryRecord('SELECT * FROM questionnaires WHERE page = ?', $page);
87        if (!$record) throw new \Exception($this->getLang('inactive'));
88
89        $record['deactivated_on'] = time();
90        $record['deactivated_by'] = $user;
91        $db->saveRecord('questionnaires', $record);
92    }
93
94    /**
95     * Has the given user answered the questionnaire for the given page?
96     *
97     * @param string $page The page of the questionnaire
98     * @param string $user The user to check
99     * @return bool
100     */
101    public function hasUserAnswered($page, $user)
102    {
103        $db = $this->getDB();
104        if (!$db) return false;
105
106        $sql = 'SELECT COUNT(*) FROM answers WHERE page = ? AND answered_by = ?';
107        return $db->queryValue($sql, $page, $user) > 0;
108    }
109
110    /**
111     * How many users have answered this questionnaire yet?
112     *
113     * @param string $page The page of the questionnaire
114     * @return int
115     */
116    public function numberOfResponses($page)
117    {
118        $db = $this->getDB();
119        if (!$db) return 0;
120
121        $sql = 'SELECT COUNT(DISTINCT answered_by) FROM answers WHERE page = ?';
122        return (int)$db->queryValue($sql, $page);
123    }
124
125    /**
126     * Does the given questionnaire accept answers currently?
127     *
128     * @param string $page The page of the questionnaire
129     * @return bool
130     */
131    public function isActive($page)
132    {
133        $record = $this->getQuestionnaire($page);
134        if (!$record) return false;
135        return empty($record['deactivated_on']);
136    }
137
138    /**
139     * Get the question IDs for a page, based on the collected answers
140     *
141     * @param $page
142     * @return array
143     */
144    public function getQuestionIDs($page)
145    {
146        $db = $this->getDB();
147        if (!$db) return [];
148
149        $sql = 'SELECT DISTINCT question FROM answers WHERE page = ?';
150        return array_column($db->queryAll($sql, $page), 'question');
151    }
152}
153