xref: /plugin/bez/mdl/ThreadFactory.php (revision bf67f2caf7e67113953edf331b401f0d6f894291)
1de02284cSSzymon Olewniczak<?php
2de02284cSSzymon Olewniczak
3de02284cSSzymon Olewniczaknamespace dokuwiki\plugin\bez\mdl;
4de02284cSSzymon Olewniczak
57fbf4c39SSzymon Olewniczakuse Assetic\Exception\Exception;
67fbf4c39SSzymon Olewniczak
7de02284cSSzymon Olewniczakclass ThreadFactory extends Factory {
8de02284cSSzymon Olewniczak
953df74e7SSzymon Olewniczak    public function get_table_view() {
1053df74e7SSzymon Olewniczak        return 'thread_view';
11de02284cSSzymon Olewniczak    }
12de02284cSSzymon Olewniczak
13de02284cSSzymon Olewniczak    public function get_years_scope() {
14de02284cSSzymon Olewniczak        $r = $this->model->sqlite->query('SELECT create_date FROM thread ORDER BY id LIMIT 1');
15de02284cSSzymon Olewniczak        $date = $this->model->sqlite->res2single($r);
16de02284cSSzymon Olewniczak
17de02284cSSzymon Olewniczak        //get only year
18de02284cSSzymon Olewniczak		$first =  (int) substr($date, 0, strpos($date, '-'));
19de02284cSSzymon Olewniczak        $last = (int) date('Y');
20de02284cSSzymon Olewniczak
21de02284cSSzymon Olewniczak		$years = array();
22de02284cSSzymon Olewniczak		for ($year = $first; $year <= $last; $year++) {
23de02284cSSzymon Olewniczak			$years[] = (string) $year;
24de02284cSSzymon Olewniczak        }
25de02284cSSzymon Olewniczak		return $years;
26de02284cSSzymon Olewniczak    }
277fbf4c39SSzymon Olewniczak
28bc2653b0SSzymon Olewniczak    public function users_involvement(\DatePeriod $period=NULL) {
29bc2653b0SSzymon Olewniczak        if ($period) {
30bc2653b0SSzymon Olewniczak            $from = $period->getStartDate()->format(\DateTime::ISO8601);
31bc2653b0SSzymon Olewniczak            $to = $period->getEndDate()->format(\DateTime::ISO8601);
32bc2653b0SSzymon Olewniczak
33eb2e6be9SSzymon Olewniczak            $sql = "SELECT thread_participant.user_id,
34eb2e6be9SSzymon Olewniczak                       SUM(thread_participant.original_poster) AS original_poster_sum,
35eb2e6be9SSzymon Olewniczak                       SUM(thread_participant.coordinator) AS coordinator_sum,
36eb2e6be9SSzymon Olewniczak                       SUM(thread_participant.commentator) AS commentator_sum,
37eb2e6be9SSzymon Olewniczak                       SUM(thread_participant.task_assignee) AS task_assignee_sum
38eb2e6be9SSzymon Olewniczak                       FROM thread_participant JOIN thread ON thread_participant.thread_id = thread.id
39eb2e6be9SSzymon Olewniczak                       WHERE thread.create_date BETWEEN ? AND ?
40eb2e6be9SSzymon Olewniczak                       GROUP BY user_id
41eb2e6be9SSzymon Olewniczak                       ORDER BY user_id";
42eb2e6be9SSzymon Olewniczak            $r = $this->model->sqlite->query($sql, $from, $to);
43eb2e6be9SSzymon Olewniczak        } else {
44eb2e6be9SSzymon Olewniczak            $sql = "SELECT user_id,
45eb2e6be9SSzymon Olewniczak                           SUM(original_poster) AS original_poster_sum,
46eb2e6be9SSzymon Olewniczak                           SUM(coordinator) AS coordinator_sum,
47eb2e6be9SSzymon Olewniczak                           SUM(commentator) AS commentator_sum,
48eb2e6be9SSzymon Olewniczak                           SUM(task_assignee) AS task_assignee_sum
49ff14b107SSzymon Olewniczak                           FROM thread_participant
50ff14b107SSzymon Olewniczak                           GROUP BY user_id
51eb2e6be9SSzymon Olewniczak                           ORDER BY user_id";
52ff14b107SSzymon Olewniczak
53ff14b107SSzymon Olewniczak            $r = $this->model->sqlite->query($sql);
54eb2e6be9SSzymon Olewniczak        }
55ff14b107SSzymon Olewniczak        return $r;
56ff14b107SSzymon Olewniczak    }
57ff14b107SSzymon Olewniczak
58bc2653b0SSzymon Olewniczak    public function kpi(\DatePeriod $period=NULL) {
59bc2653b0SSzymon Olewniczak        if ($period) {
60bc2653b0SSzymon Olewniczak            $from = $period->getStartDate()->format(\DateTime::ISO8601);
61bc2653b0SSzymon Olewniczak            $to = $period->getEndDate()->format(\DateTime::ISO8601);
62bc2653b0SSzymon Olewniczak
636fa92f54SSzymon Olewniczak            $sql = "SELECT COUNT(*)*1.0/COUNT(DISTINCT thread_id) AS kpi
646fa92f54SSzymon Olewniczak                       FROM thread_participant JOIN thread ON thread_participant.thread_id = thread.id
65a5de966aSSzymon Olewniczak                       WHERE thread.create_date BETWEEN ? AND ?";
666fa92f54SSzymon Olewniczak            $r = $this->model->sqlite->query($sql, $from, $to);
676fa92f54SSzymon Olewniczak        } else {
686fa92f54SSzymon Olewniczak            $sql = "SELECT COUNT(*)*1.0/COUNT(DISTINCT thread_id) AS kpi
696fa92f54SSzymon Olewniczak                      FROM thread_participant";
706fa92f54SSzymon Olewniczak
716fa92f54SSzymon Olewniczak            $r = $this->model->sqlite->query($sql);
726fa92f54SSzymon Olewniczak        }
736fa92f54SSzymon Olewniczak
746fa92f54SSzymon Olewniczak        return $r->fetchColumn();
756fa92f54SSzymon Olewniczak    }
766fa92f54SSzymon Olewniczak
77bc2653b0SSzymon Olewniczak    public function bez_activity(\DatePeriod $period=NULL) {
78bc2653b0SSzymon Olewniczak        if ($period) {
79bc2653b0SSzymon Olewniczak            $from = $period->getStartDate()->format(\DateTime::ISO8601);
80bc2653b0SSzymon Olewniczak            $to = $period->getEndDate()->format(\DateTime::ISO8601);
81bc2653b0SSzymon Olewniczak
82a5de966aSSzymon Olewniczak            $sql = "SELECT COUNT(DISTINCT user_id)
83a5de966aSSzymon Olewniczak                      FROM (SELECT user_id
84a5de966aSSzymon Olewniczak                              FROM thread_participant JOIN thread ON thread_participant.thread_id = thread.id
85a5de966aSSzymon Olewniczak                              WHERE create_date BETWEEN ? AND ?
86a5de966aSSzymon Olewniczak                            UNION
87a5de966aSSzymon Olewniczak                            SELECT user_id
88a5de966aSSzymon Olewniczak                              FROM task_participant JOIN task ON task_participant.task_id = task.id
89a5de966aSSzymon Olewniczak                              WHERE create_date BETWEEN ? AND ?)";
90a5de966aSSzymon Olewniczak            $r = $this->model->sqlite->query($sql, $from, $to, $from, $to);
91a5de966aSSzymon Olewniczak        } else {
92a5de966aSSzymon Olewniczak            $sql = "SELECT COUNT(DISTINCT user_id)
93a5de966aSSzymon Olewniczak                      FROM (SELECT user_id FROM thread_participant
94a5de966aSSzymon Olewniczak                            UNION
95a5de966aSSzymon Olewniczak                            SELECT user_id FROM task_participant)";
96a5de966aSSzymon Olewniczak
97a5de966aSSzymon Olewniczak            $r = $this->model->sqlite->query($sql);
98a5de966aSSzymon Olewniczak        }
99a5de966aSSzymon Olewniczak        $active_users = $r->fetchColumn();
100a5de966aSSzymon Olewniczak        $wiki_users = count($this->model->userFactory->get_all());
101a5de966aSSzymon Olewniczak
102a5de966aSSzymon Olewniczak        return $active_users/$wiki_users * 100;
103a5de966aSSzymon Olewniczak    }
104a5de966aSSzymon Olewniczak
105bc2653b0SSzymon Olewniczak
106bc2653b0SSzymon Olewniczak    public function report_issue(\DatePeriod $period=NULL) {
107bc2653b0SSzymon Olewniczak        if ($period) {
108bc2653b0SSzymon Olewniczak            $from = $period->getStartDate()->format(\DateTime::ISO8601);
109bc2653b0SSzymon Olewniczak            $to = $period->getEndDate()->format(\DateTime::ISO8601);
110bc2653b0SSzymon Olewniczak
111bc2653b0SSzymon Olewniczak            $sql = "SELECT label_name,
112bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'proposal' THEN 1 END) AS proposal,
113bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'opened' THEN 1 END) AS opened,
114bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'done' THEN 1 END) AS done,
115bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'closed' THEN 1 END) AS closed,
116bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'rejected' THEN 1 END) AS rejected,
117bc2653b0SSzymon Olewniczak                           COUNT(*) AS count_all,
118bc2653b0SSzymon Olewniczak                           SUM(task_sum_cost) AS sum_all,
119bc2653b0SSzymon Olewniczak                           SUM(CASE WHEN state = 'closed' THEN task_sum_cost END) AS sum_closed,
120bc2653b0SSzymon Olewniczak                           (CASE WHEN state = 'closed' THEN
121bc2653b0SSzymon Olewniczak                            AVG(julianday(close_date) - julianday(create_date))
122bc2653b0SSzymon Olewniczak                            END) AS avg_closed
123bc2653b0SSzymon Olewniczak                      FROM thread_view
124bc2653b0SSzymon Olewniczak                      WHERE type = 'issue' AND create_date BETWEEN ? AND ?
125bc2653b0SSzymon Olewniczak                      GROUP BY label_name
126bc2653b0SSzymon Olewniczak                      ORDER BY label_name";
127bc2653b0SSzymon Olewniczak
128bc2653b0SSzymon Olewniczak            $r = $this->model->sqlite->query($sql, $from, $to);
129bc2653b0SSzymon Olewniczak        } else {
130bc2653b0SSzymon Olewniczak            $sql = "SELECT label_name,
131bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'proposal' THEN 1 END) AS proposal,
132bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'opened' THEN 1 END) AS opened,
133bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'done' THEN 1 END) AS done,
134bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'closed' THEN 1 END) AS closed,
135bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'rejected' THEN 1 END) AS rejected,
136bc2653b0SSzymon Olewniczak                           COUNT(*) AS count_all,
137bc2653b0SSzymon Olewniczak                           SUM(task_sum_cost) AS sum_all,
138bc2653b0SSzymon Olewniczak                           SUM(CASE WHEN state = 'closed' THEN task_sum_cost END) AS sum_closed,
139bc2653b0SSzymon Olewniczak                           (CASE WHEN state = 'closed' THEN
140bc2653b0SSzymon Olewniczak                            AVG(julianday(close_date) - julianday(create_date))
141bc2653b0SSzymon Olewniczak                            END) AS avg_closed
142bc2653b0SSzymon Olewniczak                      FROM thread_view
143bc2653b0SSzymon Olewniczak                      WHERE type = 'issue'
144bc2653b0SSzymon Olewniczak                      GROUP BY label_name
145bc2653b0SSzymon Olewniczak                      ORDER BY label_name";
146bc2653b0SSzymon Olewniczak
147bc2653b0SSzymon Olewniczak            $r = $this->model->sqlite->query($sql);
148bc2653b0SSzymon Olewniczak        }
149bc2653b0SSzymon Olewniczak        return $r;
150bc2653b0SSzymon Olewniczak    }
151bc2653b0SSzymon Olewniczak
152bc2653b0SSzymon Olewniczak    public function report_project(\DatePeriod $period=NULL) {
153bc2653b0SSzymon Olewniczak        if ($period) {
154bc2653b0SSzymon Olewniczak            $from = $period->getStartDate()->format(\DateTime::ISO8601);
155bc2653b0SSzymon Olewniczak            $to = $period->getEndDate()->format(\DateTime::ISO8601);
156bc2653b0SSzymon Olewniczak
157bc2653b0SSzymon Olewniczak            $sql = "SELECT label_name,
158bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'proposal' THEN 1 END) AS proposal,
159bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'opened' THEN 1 END) AS opened,
160bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'done' THEN 1 END) AS done,
161bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'closed' THEN 1 END) AS closed,
162bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'rejected' THEN 1 END) AS rejected,
163bc2653b0SSzymon Olewniczak                           COUNT(*) AS count_all,
164bc2653b0SSzymon Olewniczak                           SUM(task_sum_cost) AS sum_all,
165bc2653b0SSzymon Olewniczak                           SUM(CASE WHEN state = 'closed' THEN task_sum_cost END) AS sum_closed,
166bc2653b0SSzymon Olewniczak                           (CASE WHEN state = 'closed' THEN
167bc2653b0SSzymon Olewniczak                            AVG(julianday(close_date) - julianday(create_date))
168bc2653b0SSzymon Olewniczak                            END) AS avg_closed
169bc2653b0SSzymon Olewniczak                      FROM thread_view
170bc2653b0SSzymon Olewniczak                      WHERE type = 'project' AND create_date BETWEEN ? AND ?";
171bc2653b0SSzymon Olewniczak
172bc2653b0SSzymon Olewniczak            $r = $this->model->sqlite->query($sql, $from, $to);
173bc2653b0SSzymon Olewniczak        } else {
174bc2653b0SSzymon Olewniczak            $sql = "SELECT label_name,
175bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'proposal' THEN 1 END) AS proposal,
176bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'opened' THEN 1 END) AS opened,
177bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'done' THEN 1 END) AS done,
178bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'closed' THEN 1 END) AS closed,
179bc2653b0SSzymon Olewniczak                           COUNT(CASE WHEN state = 'rejected' THEN 1 END) AS rejected,
180bc2653b0SSzymon Olewniczak                           COUNT(*) AS count_all,
181bc2653b0SSzymon Olewniczak                           SUM(task_sum_cost) AS sum_all,
182bc2653b0SSzymon Olewniczak                           SUM(CASE WHEN state = 'closed' THEN task_sum_cost END) AS sum_closed,
183bc2653b0SSzymon Olewniczak                           (CASE WHEN state = 'closed' THEN
184bc2653b0SSzymon Olewniczak                            AVG(julianday(close_date) - julianday(create_date))
185bc2653b0SSzymon Olewniczak                            END) AS avg_closed
186bc2653b0SSzymon Olewniczak                      FROM thread_view
187bc2653b0SSzymon Olewniczak                      WHERE type = 'project'";
188bc2653b0SSzymon Olewniczak
189bc2653b0SSzymon Olewniczak            $r = $this->model->sqlite->query($sql);
190bc2653b0SSzymon Olewniczak        }
191bc2653b0SSzymon Olewniczak        return $r;
192bc2653b0SSzymon Olewniczak    }
193bc2653b0SSzymon Olewniczak
1948a638198SSzymon Olewniczak    public function initial_save(Entity $thread, $data) {
1957fbf4c39SSzymon Olewniczak        $label_ids = array();
1967fbf4c39SSzymon Olewniczak        if (isset($data['label_id']) && $data['label_id'] != '') {
1977fbf4c39SSzymon Olewniczak            $label_ids[] = $data['label_id'];
1987fbf4c39SSzymon Olewniczak        }
1997fbf4c39SSzymon Olewniczak        try {
2007fbf4c39SSzymon Olewniczak            $this->beginTransaction();
201a0cd8c78SSzymon Olewniczak
20253df74e7SSzymon Olewniczak            parent::initial_save($thread, $data);
2037fbf4c39SSzymon Olewniczak
2047fbf4c39SSzymon Olewniczak            foreach($label_ids as $label_id) {
2057fbf4c39SSzymon Olewniczak                $thread->add_label($label_id);
2067fbf4c39SSzymon Olewniczak            }
2077fbf4c39SSzymon Olewniczak
2087fbf4c39SSzymon Olewniczak            $thread->set_participant_flags($thread->original_poster, array('original_poster', 'subscribent'));
2097fbf4c39SSzymon Olewniczak            if($thread->coordinator != null) {
2107fbf4c39SSzymon Olewniczak                $thread->set_participant_flags($thread->coordinator, array('coordinator', 'subscribent'));
2117fbf4c39SSzymon Olewniczak            }
2127fbf4c39SSzymon Olewniczak
213a0cd8c78SSzymon Olewniczak            if ($this->model->get_level() >= BEZ_AUTH_LEADER) {
21453df74e7SSzymon Olewniczak                $private = false;
21553df74e7SSzymon Olewniczak                if (isset($data['private'])) {
21653df74e7SSzymon Olewniczak                    $private = true;
21753df74e7SSzymon Olewniczak                }
21853df74e7SSzymon Olewniczak                $thread->set_private_flag($private);
21953df74e7SSzymon Olewniczak            }
22053df74e7SSzymon Olewniczak
2218a638198SSzymon Olewniczak            $this->commitTransaction();
2228a638198SSzymon Olewniczak
2238a638198SSzymon Olewniczak            if ($thread->state != 'proposal' && $this->model->user_nick != $thread->coordinator) {
2248a638198SSzymon Olewniczak                $thread->mail_inform_coordinator();
225e09b232fSSzymon Olewniczak            } elseif ($thread->state == 'proposal') {
226e09b232fSSzymon Olewniczak                $thread->mail_inform_admins();
2277fbf4c39SSzymon Olewniczak            }
22814a1f0a4SSzymon Olewniczak
22914a1f0a4SSzymon Olewniczak        } catch(Exception $exception) {
23014a1f0a4SSzymon Olewniczak            $this->rollbackTransaction();
23114a1f0a4SSzymon Olewniczak        }
2327fbf4c39SSzymon Olewniczak    }
2337fbf4c39SSzymon Olewniczak
234b90263acSSzymon Olewniczak    protected function update(Entity $obj) {
235b90263acSSzymon Olewniczak        if ($obj->state == 'done') {
2365b88664dSSzymon Olewniczak            $prev_state = $obj->state;
237b90263acSSzymon Olewniczak            $reflectionClass = new \ReflectionClass('dokuwiki\plugin\bez\mdl\Thread');
238b90263acSSzymon Olewniczak            $reflectionProperty = $reflectionClass->getProperty('state');
239b90263acSSzymon Olewniczak            $reflectionProperty->setAccessible(true);
240b90263acSSzymon Olewniczak            $reflectionProperty->setValue($obj, 'opened');
241b90263acSSzymon Olewniczak        }
242b90263acSSzymon Olewniczak        try {
243b90263acSSzymon Olewniczak            parent::update($obj);
244b90263acSSzymon Olewniczak        } finally {
2455b88664dSSzymon Olewniczak            if (isset($prev_state)) {
246b90263acSSzymon Olewniczak                $reflectionProperty->setValue($obj, $prev_state);
247b90263acSSzymon Olewniczak            }
248b90263acSSzymon Olewniczak        }
2495b88664dSSzymon Olewniczak    }
250b90263acSSzymon Olewniczak
2518a638198SSzymon Olewniczak    public function update_save(Entity $thread, $data) {
2527fbf4c39SSzymon Olewniczak        $prev_coordinator = $thread->coordinator;
25353df74e7SSzymon Olewniczak
2547fbf4c39SSzymon Olewniczak        $label_ids = array();
2557fbf4c39SSzymon Olewniczak        if (isset($data['label_id']) && $data['label_id'] != '') {
2567fbf4c39SSzymon Olewniczak            $label_ids[] = $data['label_id'];
2577fbf4c39SSzymon Olewniczak        }
2587fbf4c39SSzymon Olewniczak        try {
2597fbf4c39SSzymon Olewniczak            $this->beginTransaction();
26053df74e7SSzymon Olewniczak            parent::update_save($thread, $data);
2617fbf4c39SSzymon Olewniczak
2627fbf4c39SSzymon Olewniczak            $cur_label_ids = array_keys($thread->get_labels());
2637fbf4c39SSzymon Olewniczak            $labels_to_add = array_diff($label_ids, $cur_label_ids);
2647fbf4c39SSzymon Olewniczak            $labels_to_rem = array_diff($cur_label_ids, $label_ids);
2657fbf4c39SSzymon Olewniczak
2667fbf4c39SSzymon Olewniczak            foreach($labels_to_add as $label_id) {
2677fbf4c39SSzymon Olewniczak                $thread->add_label($label_id);
2687fbf4c39SSzymon Olewniczak            }
2697fbf4c39SSzymon Olewniczak
2707fbf4c39SSzymon Olewniczak            foreach($labels_to_rem as $label_id) {
2717fbf4c39SSzymon Olewniczak                $thread->remove_label($label_id);
2727fbf4c39SSzymon Olewniczak            }
2737fbf4c39SSzymon Olewniczak
2747fbf4c39SSzymon Olewniczak            if ($thread->coordinator != null && $thread->coordinator != $prev_coordinator) {
275eb2e6be9SSzymon Olewniczak                if ($prev_coordinator != null) {
2767fbf4c39SSzymon Olewniczak                    $thread->remove_participant_flags($prev_coordinator, array('coordinator'));
277eb2e6be9SSzymon Olewniczak                }
2787fbf4c39SSzymon Olewniczak                $thread->set_participant_flags($thread->coordinator, array('subscribent', 'coordinator'));
2797fbf4c39SSzymon Olewniczak            }
2807fbf4c39SSzymon Olewniczak
28153df74e7SSzymon Olewniczak            if ($thread->acl_of('private') >= BEZ_PERMISSION_CHANGE) {
28253df74e7SSzymon Olewniczak                $private = false;
28353df74e7SSzymon Olewniczak                if (isset($data['private'])) {
28453df74e7SSzymon Olewniczak                    $private = true;
28553df74e7SSzymon Olewniczak                }
28653df74e7SSzymon Olewniczak                $thread->set_private_flag($private);
28753df74e7SSzymon Olewniczak            }
28853df74e7SSzymon Olewniczak
2898a638198SSzymon Olewniczak            $this->commitTransaction();
2907fbf4c39SSzymon Olewniczak        } catch(Exception $exception) {
2918a638198SSzymon Olewniczak            $this->rollbackTransaction();
2928a638198SSzymon Olewniczak        }
2938a638198SSzymon Olewniczak
2948a638198SSzymon Olewniczak        if ($thread->state != 'proposal' && $this->model->user_nick != $thread->coordinator) {
2958a638198SSzymon Olewniczak            $thread->mail_inform_coordinator();
296*bf67f2caSSzymon Olewniczak        }
297*bf67f2caSSzymon Olewniczak    }
298*bf67f2caSSzymon Olewniczak
299*bf67f2caSSzymon Olewniczak    public function delete(Entity $obj) {
300*bf67f2caSSzymon Olewniczak        if ($obj->can_be_removed()) {
301*bf67f2caSSzymon Olewniczak            $this->model->sqlite->query('DELETE FROM thread_label WHERE thread_id=?', $obj->id);
302*bf67f2caSSzymon Olewniczak            parent::delete($obj);
3037fbf4c39SSzymon Olewniczak        }
3047fbf4c39SSzymon Olewniczak    }
305de02284cSSzymon Olewniczak}
306