Issues (404)

classes/EditQueue.php (8 issues)

1
<?php
2
/**
3
 * EditQueue Class
4
 *
5
 * @package TheyWorkForYou
6
 */
7
8
namespace MySociety\TheyWorkForYou;
9
10
/**
11
 * Edit Queue
12
 */
13
14
/*
15
16
[From the WIKI]
17
The EDITQUEUE is a holding point for submitted content additions or modifications before they are made on the core data. It's quite a wide table, so as to hold as many different types of addition/modification as possible.
18
19
These hold details of actions waiting to be approved, such as:
20
21
    * creation or modification of glossary entries
22
    * creation or modification of attributes
23
    * associations
24
    * anything else?
25
26
Specifying which of the above is happening is down to the edit_type field.
27
28
    * edit_id is the unique id of the EDITQUEUE record
29
    * user_id is the id of the user who submitted the edit
30
    * edit_type is the kind of edit being made
31
    * epobject_id_l and epobject_id_h hold both eopbject_ids in the case of a new association, with epobject_id_l holding the single epobject_id if the edit only applies to one object. If there's a completely new object being submitted, this is left blank until the content is approved and then filled in with the new object id.
32
    * time_start and time_end are for associations
33
    * title and body are for new or changed content for a glossary entry
34
    * submitted is the datetime that the content was initially submitted by the user
35
    * editor_id is the id of the editor who made the decision on it
36
    * approved says yay or nay to the edit
37
    * decided is the datetime when the decision was made
38
39
    While we're here...
40
    Whenever a term is added to the glossary, it appears in the editqueue first.
41
    Here it sits until a moderator has approved it, then it goes on it's merry way
42
    to whichever db it be bound.
43
44
    Functions:
45
46
    add()           - pop one on the queue (should then alert moderators somehow)
47
    approve()       - say "yes!" and forward onwards
48
    decline()       - an outright "no!", in the bin you go
49
    refer()         - pass back to the user with suggested alterations
50
    get_pending()   - fetch a list of all TODOs
51
    etc...
52
*/
53
54
// [TODO] what happens when two things with the same name are in the editqueue?
55
56
class EditQueue {
57
    public $pending_count = '';
58
59
    public function __construct() {
60
        $this->db = new \ParlDB();
0 ignored issues
show
Bug Best Practice introduced by
The property db does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
61
    }
62
63
    public function add($data) {
64
        // This does the bare minimum.
65
        // The upper object should make sure it's passsing good data.
66
        // (for now!)
67
68
        /*
69
        print "<pre>";
70
        print_r ($data);
71
        print "</pre>";
72
        */
73
74
        // For editqueue in this instance we need:
75
        //      user_id INTEGER,
76
        //      edit_type INTEGER,
77
        //      (epobject_id_l),
78
        //      title VARCHAR(255),
79
        //      body TEXT,
80
        //      submitted DATETIME,
81
82
        global $THEUSER;
83
84
        $q = $this->db->query("INSERT INTO editqueue
85
                        (user_id, edit_type, title, body, submitted)
86
                        VALUES
87
                        (
88
                        '" . addslashes($THEUSER->user_id()) . "',
89
                        '" . $data['edit_type'] . "',
90
                        '" . addslashes($data['title']) . "',
91
                        '" . addslashes($data['body']) . "',
92
                        '" . $data['posted'] . "'
93
                        );");
94
95
        if ($q->success()) {
96
            // Set the object variables up.
97
            $this->editqueue_id     = $q->insert_id();
0 ignored issues
show
Bug Best Practice introduced by
The property editqueue_id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
98
            $this->title            = $data['title'];
0 ignored issues
show
Bug Best Practice introduced by
The property title does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
99
            $this->body             = $data['body'];
0 ignored issues
show
Bug Best Practice introduced by
The property body does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
100
            $this->posted           = $data['posted'];
0 ignored issues
show
Bug Best Practice introduced by
The property posted does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
101
102
            return $this->editqueue_id;
103
104
        } else {
105
            return false;
106
        }
107
    }
108
109
    public function approve($data) {
110
        // Approve items for inclusion
111
        // Create new epobject and update the editqueue
112
113
        global $THEUSER;
114
115
        // We need a list of editqueue items to play with
116
        $this->get_pending();
117
        if (!isset($this->pending)) {
118
            return false;
119
        }
120
        $timestamp = date('Y-m-d H:i:s', time());
121
122
        foreach ($data['approvals'] as $approval_id) {
123
            // create a new epobject
124
            //      title VARCHAR(255),
125
            //      body TEXT,
126
            //      type INTEGER,
127
            //      created DATETIME,
128
            //      modified DATETIME,
129
            /*print "<pre>";
130
            print_r($data);
131
            print "</pre>";*/
132
            // Check to see that we actually have something to approve
133
            if (!isset($this->pending[$approval_id])) {
134
                break;
135
            }
136
            $q = $this->db->query("INSERT INTO epobject
137
                            (title, body, type, created)
138
                            VALUES
139
                            ('" . addslashes($this->pending[$approval_id]['title']) . "',
140
                            '" . addslashes($this->pending[$approval_id]['body']) . "',
141
                            '" . $data['epobject_type'] . "',
142
                            '" . $timestamp . "');");
143
144
            // If that didn't work we can't go any further...
145
            if (!$q->success()) {
146
                print "epobject trouble";
147
                return false;
148
            }
149
            $this->current_epobject_id = $q->insert_id();
0 ignored issues
show
Bug Best Practice introduced by
The property current_epobject_id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
150
151
            // depending on the epobject type, we'll need to make
152
            // entries in different tables.
153
            switch ($data['epobject_type']) {
154
155
                case EPTYPE_GLOSSARY:
156
                    $previous_insert_id = $q->insert_id();
157
                    $q = $this->db->query(
158
                        'INSERT INTO glossary
159
                                    (epobject_id, type, visible)
160
                                    VALUES
161
                                    (:id, :type, :enabled);',
162
                        [
163
                            ':id' => $q->insert_id(),
164
                            ':type' => EPTYPE_GLOSSARY,
165
                            ':enabled' => 1,
166
                        ]
167
                    );
168
                    // Again, no point carrying on if this fails,
169
                    // so remove the previous entry
170
                    if (!$q->success()) {
171
                        print "glossary trouble!";
172
                        $this->db->query('DELETE FROM epobject WHERE epobject_id=:id ;', [':id' => $previous_insert_id]);
173
                        return false;
174
                    }
175
                    break;
176
177
            }
178
            $this->current_subclass_id = $q->insert_id();
0 ignored issues
show
Bug Best Practice introduced by
The property current_subclass_id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
179
180
            // Then finally update the editqueue with
181
            // the new epobject id and approval details.
182
            $q = $this->db->query(
183
                'UPDATE editqueue
184
                            SET
185
                            epobject_id_l=:current,
186
                            editor_id=:editor,
187
                            approved=:approved,
188
                            decided=:timestamp
189
                            WHERE edit_id=:approval_id ;',
190
                [
191
                    ':current' => $this->current_epobject_id,
192
                    ':editor' => addslashes($THEUSER->user_id()),
193
                    ':approved' => '1',
194
                    ':timestamp' => $timestamp,
195
                    ':approval_id' => $approval_id,
196
                ]
197
            );
198
            if (!$q->success()) {
199
                break;
200
            } else {
201
                // Now send them an email telling them they've been approved
202
203
204
                // Scrub that one from the list of pending items
205
                unset($this->pending[$approval_id]);
206
            }
207
        }
208
209
        $this->update_pending_count();
210
211
        return true;
212
    }
213
214
    public function decline($data) {
215
        // Decline a list of term submissions from users
216
217
        global $THEUSER;
218
219
        // We need a list of editqueue items to play with
220
        $this->get_pending();
221
        if (!isset($this->pending)) {
222
            return false;
223
        }
224
        $timestamp = date('Y-m-d H:i:s', time());
225
226
        foreach ($data['declines'] as $decline_id) {
227
            // Check to see that we actually have something to decline
228
            if (!isset($this->pending[$decline_id])) {
229
                break;
230
            }
231
232
            // Update the editqueue with setting approved=0
233
            $q = $this->db->query("UPDATE editqueue
234
                            SET
235
                            editor_id='" . addslashes($THEUSER->user_id()) . "',
236
                            approved='0',
237
                            decided='" . $timestamp . "'
238
                            WHERE edit_id=" . $decline_id . ";");
239
            if (!$q->success()) {
240
                break;
241
            } else {
242
                // Scrub that one from the list of pending items
243
                unset($this->pending[$decline_id]);
244
            }
245
        }
246
247
        $this->update_pending_count();
248
249
        return true;
250
251
    }
252
253
    public function get_pending() {
254
        // Fetch all pending editqueue items.
255
        // Sets $this->pending and returns a body count.
256
        // Return organised by type? - maybe not for the moment
257
258
        $q = $this->db->query("SELECT eq.edit_id, eq.user_id, u.firstname, u.lastname, eq.glossary_id, eq.title, eq.body, eq.submitted FROM editqueue AS eq, users AS u WHERE eq.user_id = u.user_id AND eq.approved IS NULL ORDER BY eq.submitted DESC;");
259
        if ($q->success() && $q->rows()) {
260
            foreach ($q as $row) {
261
                $this->pending[$row['edit_id']] = $row;
0 ignored issues
show
Bug Best Practice introduced by
The property pending does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
262
            }
263
264
            $this->update_pending_count();
265
266
            return true;
267
        } else {
268
            return false;
269
        }
270
    }
271
272
    public function display() {
273
        // Print all our pending items out in a nice list or something
274
        // Add links later for "approve, decline, refer"
275
        // Just get the fucker working for now
276
277
        $URL = new Url('admin_glossary_pending');
278
        $URL->reset();
279
        $form_link = $URL->generate('url');
280
281
        ?><form action="<?php echo $form_link ?>" method="post"><?php
282
        foreach ($this->pending as $editqueue_id => $pender) {
283
284
            $URL = new Url('admin_glossary_pending');
285
            $URL->insert(['approve' => $editqueue_id]);
286
            $approve_link = $URL->generate('url');
287
288
            $URL = new Url('admin_glossary_pending');
289
            $URL->insert(['modify' => $editqueue_id]);
290
            $modify_link = $URL->generate('url');
291
292
            $URL = new Url('admin_glossary_pending');
293
            $URL->insert(['decline' => $editqueue_id]);
294
            $decline_link = $URL->generate('url');
295
296
            ?><div class="pending-item"><label for="<?php echo $editqueue_id; ?>"><input type="checkbox" name="approve[]" value="<?php echo $editqueue_id; ?>" id="<?php echo $editqueue_id; ?>"><strong><?php echo $pender['title']; ?></strong></label>
297
            <p><?php echo $pender['body']; ?><br>
298
            <small>
299
                <a href="<?php echo $approve_link; ?>">approve</a>
300
                &nbsp;|&nbsp;
301
                <a href="<?php echo $modify_link; ?>">modify</a>
302
                &nbsp;|&nbsp;
303
                <a href="<?php echo $decline_link; ?>">decline</a>
304
                <br>Submitted by: <em><?php echo $pender['firstname']; ?>&nbsp;<?php echo $pender['lastname']; ?></em>
305
            </small></p></div>
306
        <?php
307
        }
308
        ?><input type="submit" value="Approve checked items">
309
        </form><?php
310
    }
311
312
    protected function update_pending_count() {
313
        // Just makes sure we're showing the right number of pending items
314
        $this->pending_count = count($this->pending);
315
    }
316
317
}
318