GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (4873)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/common/widget/WidgetLayoutManager.class.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved
4
 *
5
 * This file is a part of Codendi.
6
 *
7
 * Codendi is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * Codendi is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
/**
22
* WidgetLayoutManager
23
*
24
* Manage layouts for users, groups and homepage
25
*/
26
class WidgetLayoutManager {
27
    const OWNER_TYPE_USER  = 'u';
28
    const OWNER_TYPE_GROUP = 'g';
29
    const OWNER_TYPE_HOME  = 'h';
30
31
    /**
32
     * @return int
33
     */
34
    function getDefaultLayoutId($owner_id, $owner_type) {
35
        $sql = "SELECT l.*
36
            FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = o.layout_id)
37
            WHERE o.owner_type = '". $owner_type ."'
38
              AND o.owner_id = ". $owner_id ."
39
              AND o.is_default = 1
40
        ";
41
        $req = db_query($sql);
42
        if ($data = db_fetch_array($req)) {
43
            return $data['id'];
44
        }
45
        return null;
46
    }
47
48
    /**
49
    * displayLayout
50
    *
51
    * Display the default layout for the "owner". It my be the home page, the project summary page or /my/ page.
52
    *
53
    * @param  owner_id
54
    * @param  owner_type
55
    */
56
    function displayLayout($owner_id, $owner_type) {
57
        $sql = "SELECT l.*
58
            FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = o.layout_id)
59
            WHERE o.owner_type = '". $owner_type ."'
60
              AND o.owner_id = ". $owner_id ."
61
              AND o.is_default = 1
62
        ";
63
        $req = db_query($sql);
64
        if ($data = db_fetch_array($req)) {
65
            $readonly = !$this->_currentUserCanUpdateLayout($owner_id, $owner_type);
66
            if (!$readonly) {
67
                echo '<a href="/widgets/widgets.php?owner='. $owner_type.$owner_id .'&amp;layout_id='. $data['id'] .'" class="layout_manager_customize btn btn-small"><i class="icon-cog"></i> '. $GLOBALS['Language']->getText('widget_add', 'link_add') .'</a>';
68
            } else if ($owner_type === self::OWNER_TYPE_GROUP) {
69
                echo '<br />';
70
            }
71
            $layout = new WidgetLayout($data['id'], $data['name'], $data['description'], $data['scope']);
72
            $sql = 'SELECT * FROM layouts_rows WHERE layout_id = '. $layout->id .' ORDER BY rank';
73
            $req_rows = db_query($sql);
74
            while ($data = db_fetch_array($req_rows)) {
75
                $row = new WidgetLayout_Row($data['id'], $data['rank']);
76
                $sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id = '. $row->id;
77
                $req_cols = db_query($sql);
78
                while ($data = db_fetch_array($req_cols)) {
79
                    $col = new WidgetLayout_Row_Column($data['id'], $data['width']);
80
                    $sql = "SELECT * FROM layouts_contents WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id .' AND column_id = '. $col->id .' ORDER BY rank';
81
                    $req_content = db_query($sql);
82
                    while ($data = db_fetch_array($req_content)) {
83
                        $c = Widget::getInstance($data['name']);
84
                        if ($c && $c->isAvailable()) {
85
                            $c->loadContent($data['content_id']);
86
                            $col->add($c, $data['is_minimized'], $data['display_preferences']);
87
                        }
88
                        unset($c);
89
                    }
90
                    $row->add($col);
91
                    unset($col);
92
                }
93
                $layout->add($row);
94
                unset($row);
95
            }
96
            $layout->display($readonly, $owner_id, $owner_type);
97
        }
98
    }
99
100
    /**
101
    * _currentUserCanUpdateLayout
102
    *
103
    * @return boolean true if the user dan uppdate the layout (add/remove widget, collapse, set preferences, ...)
104
    * @param  owner_id
105
    * @param  owner_type
106
    */
107
    function _currentUserCanUpdateLayout($owner_id, $owner_type) {
108
        $readonly = true;
109
        $request = HTTPRequest::instance();
110
        switch ($owner_type) {
111
        case self::OWNER_TYPE_USER:
112
                if (user_getid() == $owner_id) { //Current user can only update its own /my/ page
113
                    $readonly = false;
114
                }
115
                break;
116
            case self::OWNER_TYPE_GROUP:
117
                if (user_is_super_user() || user_ismember($request->get('group_id'), 'A')) { //Only project admin
118
                    $readonly = false;
119
                }
120
                break;
121
            case self::OWNER_TYPE_HOME:
122
                //Only site admin
123
                break;
124
            default:
125
                break;
126
        }
127
        return !$readonly;
128
    }
129
    /**
130
    * createDefaultLayoutForUser
131
    *
132
    * Create the first layout for the user and add some initial widgets:
133
    * - MyArtifacts
134
    * - MyProjects
135
    * - MyBookmarks
136
    * - MySurveys
137
    * - MyMonitoredFP
138
    * - MyMonitoredForums
139
    * - and widgets of plugins if they want to listen to the event default_widgets_for_new_owner
140
    *
141
    * @param  owner_id The id of the newly created user
142
    */
143
    function createDefaultLayoutForUser($owner_id) {
144
        $service_manager = ServiceManager::instance();
145
        $owner_type = self::OWNER_TYPE_USER;
146
        $sql = "INSERT INTO owner_layouts(layout_id, is_default, owner_id, owner_type) VALUES (1, 1, $owner_id, '$owner_type')";
147
        if (db_query($sql)) {
148
149
            $sql = "INSERT INTO layouts_contents(owner_id, owner_type, layout_id, column_id, name, rank) VALUES ";
150
            $sql .= "($owner_id, '$owner_type', 1, 1, 'myprojects', 0)";
151
            $sql .= ",($owner_id, '$owner_type', 1, 1, 'mybookmarks', 1)";
152
            if ($service_manager->isServiceAvailableAtSiteLevelByShortName(Service::FORUM)) {
153
                $sql .= ",($owner_id, '$owner_type', 1, 1, 'mymonitoredforums', 2)";
154
            }
155
            if ($service_manager->isServiceAvailableAtSiteLevelByShortName(Service::SURVEY)) {
156
                $sql .= ",($owner_id, '$owner_type', 1, 1, 'mysurveys', 4)";
157
            }
158
            if ($service_manager->isServiceAvailableAtSiteLevelByShortName(Service::TRACKERV3)) {
159
                $sql .= ",($owner_id, '$owner_type', 1, 2, 'myartifacts', 10)";
160
            }
161
            if ($service_manager->isServiceAvailableAtSiteLevelByShortName(Service::FILE)) {
162
                $sql .= ",($owner_id, '$owner_type', 1, 2, 'mymonitoredfp', 20)";
163
            }
164
165
            $em = EventManager::instance();
166
            $widgets = array();
167
            $em->processEvent('default_widgets_for_new_owner', array('widgets' => &$widgets, 'owner_type' => $owner_type));
168
            foreach($widgets as $widget) {
169
                $sql .= ",($owner_id, '$owner_type', 1, ". $widget['column'] .", '". $widget['name'] ."', ". $widget['rank'] .")";
170
            }
171
            db_query($sql);
172
        }
173
        echo db_error();
174
    }
175
176
    /**
177
    * createDefaultLayoutForProject
178
    *
179
    * Create the first layout for a new project, based on its parent template.
180
    * Add some widgets based also on its parent configuration and on its service configuration.
181
    *
182
    * @param  group_id  the id of the newly created project
183
    * @param  template_id  the id of the project template
184
    */
185
    function createDefaultLayoutForProject($group_id, $template_id) {
186
        $pm = ProjectManager::instance();
187
        $pm->clear($group_id);
188
        $project = $pm->getProject($group_id);
189
        $sql = "INSERT INTO owner_layouts(layout_id, is_default, owner_id, owner_type)
190
        SELECT layout_id, is_default, $group_id, owner_type
191
        FROM owner_layouts
192
        WHERE owner_type = '". self::OWNER_TYPE_GROUP ."'
193
          AND owner_id = $template_id
194
        ";
195
        if (db_query($sql)) {
196
            $sql = "SELECT layout_id, column_id, name, rank, is_minimized, is_removed, display_preferences, content_id
197
            FROM layouts_contents
198
            WHERE owner_type = '". self::OWNER_TYPE_GROUP ."'
199
              AND owner_id = $template_id
200
            ";
201
            if ($req = db_query($sql)) {
202
                while($data = db_fetch_array($req)) {
203
                    $w = Widget::getInstance($data['name']);
204
                    if ($w) {
205
                        $w->setOwner($template_id, self::OWNER_TYPE_GROUP);
206
                        if ($w->canBeUsedByProject($project)) {
207
                            $content_id = $w->cloneContent($w->content_id, $group_id, self::OWNER_TYPE_GROUP);
208
                            $sql = "INSERT INTO layouts_contents(owner_id, owner_type, content_id, layout_id, column_id, name, rank, is_minimized, is_removed, display_preferences)
209
                            VALUES (". $group_id .", '". self::OWNER_TYPE_GROUP ."', ". $content_id .", ". $data['layout_id'] .", ". $data['column_id'] .", '". $data['name'] ."', ". $data['rank'] .", ". $data['is_minimized'] .", ". $data['is_removed'] .", ". $data['display_preferences'] .")
210
                            ";
211
                            db_query($sql);
212
                            echo db_error();
213
                        }
214
                    }
215
                }
216
            }
217
        }
218
        echo db_error();
219
    }
220
221
    /**
222
    * displayAvailableWidgets
223
    *
224
    * Display all widget that the user can add to the layout
225
    *
226
    * @param  owner_id
227
    * @param  owner_type
228
    * @param  layout_id
229
    */
230
    function displayAvailableWidgets($owner_id, $owner_type, $layout_id) {
231
        $used_widgets = array();
232
        $sql = "SELECT *
233
        FROM layouts_contents
234
        WHERE owner_type = '". $owner_type ."'
235
        AND owner_id = ". $owner_id .'
236
        AND layout_id = '. $layout_id .'
237
        AND content_id = 0 AND column_id <> 0';
238
        $res = db_query($sql);
239
        while($data = db_fetch_array($res)) {
240
            $used_widgets[] = $data['name'];
241
        }
242
        echo '<ul class="widget_toolbar">';
243
        $parameters = array(
244
            'owner' => $owner_type.$owner_id
245
        );
246
        if ($update_layout = HTTPRequest::instance()->get('update') == 'layout') {
247
            echo '<li><a href="'. str_replace('&update=layout', '', $_SERVER['REQUEST_URI']) .'">'. $GLOBALS['Language']->getText('widget_add', 'title') .'</a></li>';
248
            echo '<li class="current"><a href="'. $_SERVER['REQUEST_URI'] .'">'. $GLOBALS['Language']->getText('widget_layout', 'title') .'</a></li>';
249
            $parameters['action'] = 'layout';
250
        } else {
251
            echo '<li class="current"><a href="'. $_SERVER['REQUEST_URI'] .'">'. $GLOBALS['Language']->getText('widget_add', 'title') .'</a></li>';
252
            echo '<li><a href="'. $_SERVER['REQUEST_URI'] .'&amp;update=layout">'. $GLOBALS['Language']->getText('widget_layout', 'title') .'</a></li>';
253
            $parameters['action']    = 'widget';
254
            $parameters['layout_id'] = $layout_id;
255
        }
256
        echo '</ul>';
257
        echo '<form action="/widgets/updatelayout.php?'. http_build_query($parameters) .'" method="POST">';
258
        if ($update_layout) {
259
            $sql = "SELECT * FROM layouts WHERE scope='S' ORDER BY id ";
260
            $req_layouts = db_query($sql);
261
            echo '<table cellspacing="0" cellpading="0">';
262
            $is_custom = true;
263
            while ($data = db_fetch_array($req_layouts)) {
264
                $checked = $layout_id == $data['id'] ? 'checked="checked"' : '';
265
                $is_custom = $is_custom && !$checked;
266
                echo '<tr class="layout-manager-chooser '. ($checked ? 'layout-manager-chooser_selected' : '') .'" ><td>';
267
                echo '<input type="radio" name="layout_id" value="'. $data['id'] .'" id="layout_'. $data['id'] .'" '. $checked .'/>';
268
                echo '</td><td>';
269
                echo '<label for="layout_'. $data['id'] .'">';
270
                echo $GLOBALS['HTML']->getImage('layout/'. strtolower(preg_replace('/(\W+)/', '-', $data['name'])) .'.png');
271
                echo '</label>';
272
                echo '</td><td>';
273
                echo '<label for="layout_'. $data['id'] .'"><strong>'. $data['name'] .'</strong><br />';
274
                echo $data['description'];
275
                echo '</label>';
276
                echo '</td></tr>';
277
            }
278
            /* Custom layout are not available yet */
279
            $checked = $is_custom ? 'checked="checked"' : '';
280
            echo '<tr class="layout-manager-chooser '. ($checked ? 'layout-manager-chooser_selected' : '') .'"><td>';
281
            echo '<input type="radio" name="layout_id" value="-1" id="layout_custom" '. $checked .'/>';
282
            echo '</td><td>';
283
            echo '<label for="layout_custom">';
284
            echo $GLOBALS['HTML']->getImage('layout/custom.png', array('style' => 'vertical-align:top;float:left;'));
285
            echo '</label>';
286
            echo '</td><td>';
287
            echo '<label for="layout_custom"><strong>'. 'Custom' .'</strong><br />';
288
            echo 'Define your own layout:';
289
            echo '</label>';
290
            echo '<table id="layout-manager" cellpadding="0" cellspacing="0">
291
                    <tr>
292
                      <td>
293
                        <div class="layout-manager-row-add">+</div>';
294
            $sql = 'SELECT * FROM layouts_rows WHERE layout_id = '. $layout_id .' ORDER BY rank';
295
            $req_rows = db_query($sql);
296
            while ($data = db_fetch_array($req_rows)) {
297
                echo '<table class="layout-manager-row" cellspacing="5" cellpadding="2" border="0">
298
                        <tr>
299
                          <td class="layout-manager-column-add">+</td>';
300
                $sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id = '. $data['id'];
301
                $req_cols = db_query($sql);
302
                while ($data = db_fetch_array($req_cols)) {
303
                    echo '<td class="layout-manager-column">
304
                            <div class="layout-manager-column-remove">x</div>
305
                            <div class="layout-manager-column-width">
306
                                <input type="text" value="'. $data['width'] .'" autocomplete="off" size="1" maxlength="3" />%
307
                            </div>
308
                          </td>
309
                          <td class="layout-manager-column-add">+</td>';
310
                }
311
                echo '  </tr>
312
                      </table>
313
                      <div class="layout-manager-row-add">+</div>';
314
            }
315
            echo '    </td>
316
                    </tr>
317
                  </table>';
318
            echo '</td></tr>';
319
            echo '</table>';
320
            echo '<input type="submit" id="save" value="'. $GLOBALS['Language']->getText('global', 'btn_submit') .'" />';
321
        } else {
322
            $after = '';
323
            echo '<table cellpadding="0" cellspacing="0">
324
                    <tbody>
325
                        <tr valign="top">
326
                            <td>';
327
                            echo '<table cellpadding="2" cellspacing="0">
328
                                    <tbody>';
329
                                    $after .= $this->_displayWidgetsSelectionForm($owner_id, $GLOBALS['Language']->getText('widget_add', 'codendi_widgets', $GLOBALS['sys_name']), Widget::getCodendiWidgets($owner_type), $used_widgets);
330
                                    echo '</tbody>
331
                                </table>';
332
                            echo '</td>
333
                            <td id="widget-content-categ">'. $after .'</td>
334
                        </tr>
335
                    </tbody>
336
                </table>';
337
        }
338
        echo '</form>';
339
    }
340
341
    function updateLayout($owner_id, $owner_type, $layout, $custom_layout) {
342
        $sql = "SELECT l.*
343
            FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = o.layout_id)
344
            WHERE o.owner_type = '". $owner_type ."'
345
              AND o.owner_id = ". $owner_id ."
346
              AND o.is_default = 1
347
        ";
348
        $req = db_query($sql);
349
        if ($data = db_fetch_array($req)) {
350
            if ($this->_currentUserCanUpdateLayout($owner_id, $owner_type)) {
351
                $old_scope         = $data['scope'];
352
                $old_layout_id = $data['id'];
353
                $new_layout_id = null;
354
                if ($layout == '-1' && is_array($custom_layout)) {
355
                    //Create a new layout based on the custom layout structure defined by the user
356
                    $rows = array();
357
                    foreach($custom_layout as $widths) {
358
                        $row = array();
359
                        $cols = explode(',', $widths);
360
                        foreach($cols as $col) {
361
                            if ($width = (int)$col) {
362
                                $row[] = $width;
363
                            }
364
                        }
365
                        if (count($row)) {
366
                            $rows[] = $row;
367
                        }
368
                    }
369
                    //If the structure contains at least one column, create a new layout
370
                    if (count($rows)) {
371
                        $sql = "INSERT INTO layouts(name, description, scope)
372
                                VALUES ('custom', '', 'P')";
373
                        if (db_query($sql)) {
374
                            $sql = "SELECT LAST_INSERT_ID() AS id";
375
                            if ($res = db_query($sql)) {
376
                                if ($data = db_fetch_array($res)) {
377
                                    $new_layout_id = $data['id'];
378
379
                                    //Create rows & columns
380
                                    $rank = 0;
381
                                    foreach($rows as $cols) {
382
                                        $sql = "INSERT INTO layouts_rows(layout_id, rank)
383
                                                VALUES ($new_layout_id, ". $rank++ .")";
384
                                        if (db_query($sql)) {
385
                                            $sql = "SELECT LAST_INSERT_ID() AS id";
386
                                            if ($res = db_query($sql)) {
387
                                                if ($data = db_fetch_array($res)) {
388
                                                    $row_id = $data['id'];
389
                                                    foreach($cols as $width) {
390
                                                        $sql = "INSERT INTO layouts_rows_columns(layout_row_id, width)
391
                                                                VALUES ($row_id, ". $width .")";
392
                                                        db_query($sql);
393
                                                    }
394
                                                }
395
                                            }
396
                                        }
397
                                    }
398
                                }
399
                            }
400
                        }
401
                    }
402
                } else {
403
                    $new_layout_id = $layout;
404
                }
405
406
                if ($new_layout_id) {
407
                    //Retrieve columns of old layout
408
                    $old = $this->_retrieveStructureOfLayout($old_layout_id);
409
410
                    //Retrieve columns of new layout
411
                    $new = $this->_retrieveStructureOfLayout($new_layout_id);
412
413
                    //Switch content from old columns to knew columns
414
                    $last_new_col_id = null;
415
                    reset($new['columns']);
416
                    foreach($old['columns'] as $old_col) {
417
                        if (list(,$new_col) = each($new['columns'])) {
418
                            $last_new_col_id = $new_col['id'];
419
                        }
420
                        $sql = "UPDATE layouts_contents
421
                                SET layout_id  = ". $new_layout_id ."
422
                                  , column_id  = ". $last_new_col_id ."
423
                                WHERE owner_type = '". $owner_type ."'
424
                                  AND owner_id   = ". $owner_id ."
425
                                  AND layout_id  = ". $old_layout_id ."
426
                                  AND column_id  = ". $old_col['id'];
427
                        db_query($sql);
428
                    }
429
                    $sql = "UPDATE owner_layouts
430
                                SET layout_id  = ". $new_layout_id ."
431
                                WHERE owner_type = '". $owner_type ."'
432
                                  AND owner_id   = ". $owner_id ."
433
                                  AND layout_id  = ". $old_layout_id;
434
                    db_query($sql);
435
436
                    //If the old layout is custom remove it
437
                    if ($old_scope != 'S') {
438
                        $structure = $this->_retrieveStructureOfLayout($old_layout_id);
439
                        foreach($structure['rows'] as $row) {
440
                            $sql = "DELETE FROM layouts_rows
441
                                    WHERE id  = ". $row['id'];
442
                            db_query($sql);
443
                            $sql = "DELETE FROM layouts_rows_columns
444
                                    WHERE layout_row_id  = ". $row['id'];
445
                            db_query($sql);
446
                        }
447
                        $sql = "DELETE FROM layouts
448
                                WHERE id  = ". $old_layout_id;
449
                        db_query($sql);
450
                    }
451
452
                }
453
            }
454
        }
455
        $this->feedback($owner_id, $owner_type);
456
    }
457
458
    function _retrieveStructureOfLayout($layout_id) {
459
        $structure = array('rows' => array(), 'columns' => array());
460
        $sql = 'SELECT * FROM layouts_rows WHERE layout_id = '. $layout_id .' ORDER BY rank';
461
        $req_rows = db_query($sql);
462
        while ($row = db_fetch_array($req_rows)) {
463
            $structure['rows'][] = $row;
464
            $sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id = '. $row['id'] .' ORDER BY id';
465
            $req_cols = db_query($sql);
466
            while ($col = db_fetch_array($req_cols)) {
467
                $structure['columns'][] = $col;
468
            }
469
        }
470
        return $structure;
471
    }
472
473
    /**
474
    * _displayWidgetsSelectionForm
475
    *
476
    * @param  title
477
    * @param  widgets
478
    * @param  used_widgets
479
    */
480
    function _displayWidgetsSelectionForm($owner_id, $title, $widgets, $used_widgets) {
481
        $hp = Codendi_HTMLPurifier::instance();
482
        $additionnal_html = '';
483
        if (count($widgets)) {
484
            echo '<tr><td colspan="2">';
485
            $categs = $this->getCategories($widgets);
486
            $widget_rows = array();
487
            if (count($categs)) {
488
                foreach($categs as $c => $ws) {
489
                    $widget_rows[$c] = '<a class="widget-categ-switcher" href="#widget-categ-'. $c .'"><span>'.   $hp->purify($GLOBALS['Language']->getText('widget_categ_label', $c), CODENDI_PURIFIER_CONVERT_HTML)  .'</span></a>';
490
                }
491
                uksort($widget_rows, 'strnatcasecmp');
492
                echo '<ul id="widget-categories">';
493
                foreach($widget_rows as $row) {
494
                    echo '<li>'. $row .'</li>';
495
                }
496
                echo '</ul>';
497
                echo '</td></tr>';
498
            } else {
499
                echo '</td></tr>';
500
                foreach($widgets as $widget_name) {
501
                    if ($widget = Widget::getInstance($widget_name)) {
502
                        if ($widget->isAvailable()) {
503
                            $row = '';
504
                            $row .= '<td>'. $widget->getTitle() . $widget->getInstallPreferences() .'</td>';
0 ignored issues
show
The call to getInstallPreferences() misses a required argument $owner_id.

This check looks for function calls that miss required arguments.

Loading history...
505
                            $row .= '<td align="right">';
506
                            if ($widget->isUnique() && in_array($widget_name, $used_widgets)) {
507
                                $row .= '<em>'. $GLOBALS['Language']->getText('widget_add', 'already_used') .'</em>';
508
                            } else {
509
                                $row .= '<input type="submit" name="name['. $widget_name .'][add]" value="'. $GLOBALS['Language']->getText('widget_add', 'add') .'" />';
510
                            }
511
                            $row .= '</td>';
512
                            $widget_rows[$widget->getTitle()] = $row;
513
                        }
514
                    }
515
                }
516
                $i = 0;
517
                foreach($widget_rows as $row) {
518
                    echo '<tr class="'. (count($widget_rows) ? '' : util_get_alt_row_color($i++)) .'">'. $row .'</tr>';
519
                }
520
            }
521
            if (count($categs)) {
522
                foreach($categs as $c => $ws) {
523
                    $i = 0;
524
                    $widget_rows = array();
525
                    foreach($ws as $widget_name => $widget) {
526
                        $row = '';
527
                        $row .= '<div class="widget-preview '. $widget->getPreviewCssClass() .'">';
528
                        $row .= '<strong>'. $widget->getTitle()  .'</strong>';
529
                        $row .= '<p>'. $widget->getDescription() .'</p>';
530
                        if ($widget->isInstallAllowed()) {
531
                            $row .= $widget->getInstallPreferences($owner_id);
532
                            $row .= '</div><div style="text-align:right; border-bottom:1px solid #ddd; padding-bottom:10px; margin-bottom:20px;">';
533
                            if ($widget->isUnique() && in_array($widget_name, $used_widgets)) {
534
                                $row .= '<em>'. $GLOBALS['Language']->getText('widget_add', 'already_used') .'</em>';
535
                            } else {
536
                                $row .= '<input type="submit" name="name['. $widget_name .'][add]" value="'. $GLOBALS['Language']->getText('widget_add', 'add') .'" />';
537
                            }
538
                            $row .= '</div>';
539
                        } else {
540
                            $row .= $widget->getInstallNotAllowedMessage();
541
                            $row .= '</div><div style="text-align:right; border-bottom:1px solid #ddd; padding-bottom:10px; margin-bottom:20px;"></div>';
542
                        }
543
                        $widget_rows[$widget->getTitle()] = $row;
544
                    }
545
                    uksort($widget_rows, 'strnatcasecmp');
546
                    $additionnal_html .= '<div id="widget-categ-'. $c .'"><h4 class="boxtitle">'. $hp->purify($GLOBALS['Language']->getText('widget_categ_label', $c), CODENDI_PURIFIER_CONVERT_HTML) .'</h4>';
547
                    foreach($widget_rows as $row) {
548
                        $additionnal_html .= $row;
549
                    }
550
                    $additionnal_html .= '</div>';
551
                }
552
            }
553
        }
554
        return $additionnal_html;
555
    }
556
    function getCategories($widgets) {
557
        $categ = array();
558
        foreach($widgets as $widget_name) {
559
            if ($widget = Widget::getInstance($widget_name)) {
560
                if ($widget->isAvailable()) {
561
                    $cs = explode(',', $widget->getCategory());
562
                    foreach($cs as $c) {
563
                        if ($c = trim($c)) {
564
                            if (!isset($categ[$c])) {
565
                                $categ[$c] = array();
566
                            }
567
                            $categ[$c][$widget_name] = $widget;
568
                        }
569
                    }
570
                }
571
            }
572
        }
573
        return $categ;
574
    }
575
    /**
576
    * addWidget
577
    *
578
    * @param  owner_id
579
    * @param  owner_type
580
    * @param  layout_id
581
    * @param  name
582
    * @param  widget
583
    * @param  request
584
    */
585
    function addWidget($owner_id, $owner_type, $layout_id, $name, &$widget, &$request) {
586
        //Search for the right column. (The first used)
587
        $sql = "SELECT u.column_id AS id
588
        FROM layouts_contents AS u
589
        LEFT JOIN (SELECT r.rank AS rank, c.id as id
590
        FROM layouts_rows AS r INNER JOIN layouts_rows_columns AS c
591
        ON (c.layout_row_id = r.id)
592
        WHERE r.layout_id = $layout_id) AS col
593
        ON (u.column_id = col.id)
594
        WHERE u.owner_type = '". $owner_type ."'
595
          AND u.owner_id = ". $owner_id ."
596
          AND u.layout_id = $layout_id
597
          AND u.column_id <> 0
598
        ORDER BY col.rank, col.id";
599
        $res = db_query($sql);
600
        echo db_error();
601
        $column_id = db_result($res, 0, 'id');
602
        if (!$column_id) {
603
            $sql = "SELECT r.rank AS rank, c.id as id
604
                    FROM layouts_rows AS r
605
                         INNER JOIN layouts_rows_columns AS c
606
                         ON (c.layout_row_id = r.id)
607
                    WHERE r.layout_id = $layout_id
608
                    ORDER BY rank, id";
609
            $res = db_query($sql);
610
            $column_id = db_result($res, 0, 'id');
611
        }
612
613
        //content_id
614
        if ($widget->isUnique()) {
615
            //unique widgets do not have content_id
616
            $content_id = 0;
617
        } else {
618
            $content_id = $widget->create($request);
619
        }
620
621
        //See if it already exists but not used
622
        $sql = "SELECT column_id FROM layouts_contents
623
        WHERE owner_type = '". $owner_type ."'
624
          AND owner_id = ". $owner_id ."
625
          AND layout_id = $layout_id
626
          AND name = '$name'";
627
        $res = db_query($sql);
628
        echo db_error();
629
        if (db_numrows($res) && !$widget->isUnique() && db_result($res, 0, 'column_id') == 0) {
630
            //search for rank
631
            $sql = "SELECT min(rank) - 1 AS rank FROM layouts_contents WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id ." AND layout_id = $layout_id AND column_id = $column_id ";
632
            $res = db_query($sql);
633
            echo db_error();
634
            $rank = db_result($res, 0, 'rank');
635
636
            //Update
637
            $sql = "UPDATE layouts_contents
638
                SET column_id = ". $column_id .", rank = $rank
639
                WHERE owner_type = '". $owner_type ."'
640
                  AND owner_id = ". $owner_id ."
641
                  AND name = '$name'
642
                  AND layout_id = ". $layout_id;
643
            $res = db_query($sql);
644
            echo db_error();
645
        } else {
646
            //Insert
647
            $sql = "INSERT INTO layouts_contents(owner_type, owner_id, layout_id, column_id, name, content_id, rank)
648
            SELECT R1.owner_type, R1.owner_id, R1.layout_id, R1.column_id, '$name', $content_id, IFNULL(R2.rank, 1) - 1
649
            FROM ( SELECT '$owner_type' AS owner_type, $owner_id AS owner_id, $layout_id AS layout_id, $column_id AS column_id ) AS R1
650
            LEFT JOIN layouts_contents AS R2 USING ( owner_type, owner_id, layout_id, column_id )
651
            ORDER BY rank ASC
652
            LIMIT 1";
653
            db_query($sql);
654
            echo db_error();
655
        }
656
        $this->feedback($owner_id, $owner_type);
657
    }
658
659
    protected function feedback($owner_id, $owner_type) {
660
        $link = '/';
661
        if ($owner_type == self::OWNER_TYPE_GROUP) {
662
            //retrieve the short name of the project
663
            if ($project = ProjectManager::instance()->getProject($owner_id)) {
664
                $hp = Codendi_HTMLPurifier::instance();
665
                $link = '/projects/'.  $hp->purify($project->getUnixName(), CODENDI_PURIFIER_CONVERT_HTML) ;
666
            }
667
        } else if ($owner_type == self::OWNER_TYPE_USER) {
668
            $link = '/my/';
669
        }
670
        $GLOBALS['Response']->addFeedback('info', $GLOBALS['Language']->getText('widget_dashboard', 'updated', $link), CODENDI_PURIFIER_DISABLED);
671
    }
672
673
    /**
674
    * removeWidget
675
    *
676
    * @param  owner_id
677
    * @param  owner_type
678
    * @param  layout_id
679
    * @param  name
680
    * @param  instance_id
681
    */
682
    function removeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id, &$widget) {
683
        $sql = "DELETE FROM layouts_contents WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id ." AND layout_id = $layout_id AND name = '$name' AND content_id = $instance_id";
684
        db_query($sql);
685
        if (!db_error()) {
686
            $widget->destroy($instance_id);
687
        }
688
    }
689
690
    /**
691
    * mimizeWidget
692
    *
693
    * @param  owner_id
694
    * @param  owner_type
695
    * @param  layout_id
696
    * @param  name
697
    * @param  instance_id
698
    */
699
    function mimizeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id) {
700
        $sql = "UPDATE layouts_contents SET is_minimized = 1 WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id ." AND layout_id = ". $layout_id ." AND name = '". db_escape_string($name) ."' AND content_id = $instance_id";
701
        db_query($sql);
702
        echo db_error();
703
    }
704
705
    /**
706
    * maximizeWidget
707
    *
708
    * @param  owner_id
709
    * @param  owner_type
710
    * @param  layout_id
711
    * @param  name
712
    * @param  instance_id
713
    */
714
    function maximizeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id) {
715
        $sql = "UPDATE layouts_contents SET is_minimized = 0 WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id ." AND layout_id = ". $layout_id ." AND name = '". db_escape_string($name) ."' AND content_id = $instance_id";
716
        db_query($sql);
717
        echo db_error();
718
    }
719
720
    /**
721
    * displayWidgetPreferences
722
    *
723
    * @param  owner_id
724
    * @param  owner_type
725
    * @param  layout_id
726
    * @param  name
727
    * @param  instance_id
728
    */
729
    function displayWidgetPreferences($owner_id, $owner_type, $layout_id, $name, $instance_id) {
730
        $sql = "UPDATE layouts_contents SET display_preferences = 1, is_minimized = 0 WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id ." AND layout_id = ". $layout_id ." AND name = '". db_escape_string($name) ."' AND content_id = $instance_id";
731
        db_query($sql);
732
        echo db_error();
733
    }
734
735
    /**
736
    * hideWidgetPreferences
737
    *
738
    * @param  owner_id
739
    * @param  owner_type
740
    * @param  layout_id
741
    * @param  name
742
    * @param  instance_id
743
    */
744
    function hideWidgetPreferences($owner_id, $owner_type, $layout_id, $name, $instance_id) {
745
        $sql = "UPDATE layouts_contents SET display_preferences = 0 WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id ." AND layout_id = ". $layout_id ." AND name = '". db_escape_string($name) ."' AND content_id = $instance_id";
746
        db_query($sql);
747
        echo db_error();
748
    }
749
750
    /**
751
    * reorderLayout
752
    *
753
    * @param  owner_id
754
    * @param  owner_type
755
    * @param  layout_id
756
    * @param  name
757
    * @param  instance_id
758
    */
759
    function reorderLayout($owner_id, $owner_type, $layout_id, &$request) {
760
        $keys = array_keys($_REQUEST);
761
        foreach($keys as $key) {
762
            if (preg_match('`widgetlayout_col_\d+`', $key)) {
763
764
765
                $split = explode('_', $key);
766
                $column_id = (int)$split[count($split)-1];
767
768
                $names = array();
769
                foreach($request->get($key) as $name) {
770
                    list($name, $id) = explode('-', $name);
771
                    $names[] = array($id, db_escape_string($name));
772
                }
773
774
                //Compute differences
775
                $originals = array();
776
                $sql = "SELECT * FROM layouts_contents WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id ." AND column_id = ". $column_id .' ORDER BY rank';
777
                $res = db_query($sql);
778
                echo db_error();
779
                while($data = db_fetch_array($res)) {
780
                    $originals[] = array($data['content_id'], db_escape_string($data['name']));
781
                }
782
783
                //delete removed contents
784
                $deleted_names = $this->_array_diff_names($originals, $names);
785
                if (count($deleted_names)) {
786
                    $_and = '';
787
                    foreach($deleted_names as $id => $name) {
788
                        if ($_and) {
789
                            $_and .= ' OR ';
790
                        } else {
791
                            $_and .= ' AND (';
792
                        }
793
                        $_and .= " (name = '".$name[1]."' AND content_id = ". $name[0] .") ";
794
                    }
795
                    $_and .= ')';
796
                    $sql = "UPDATE layouts_contents
797
                        SET column_id = 0
798
                        WHERE owner_type = '". $owner_type ."'
799
                          AND owner_id = ". $owner_id .'
800
                          AND column_id = '. $column_id .
801
                          $_and;
802
                    $res = db_query($sql);
803
                    echo db_error();
804
                }
805
806
                //Insert new contents
807
                $added_names = $this->_array_diff_names($names, $originals);
808
                if (count($added_names)) {
809
                    $_and = '';
810
                    foreach($added_names as $name) {
811
                        if ($_and) {
812
                            $_and .= ' OR ';
813
                        } else {
814
                            $_and .= ' AND (';
815
                        }
816
                        $_and .= " (name = '".$name[1]."' AND content_id = ". $name[0] .") ";
817
                    }
818
                    $_and .= ')';
819
                    //old and new column must be part of the same layout
820
                    $sql = 'UPDATE layouts_contents
821
                        SET column_id = '. $column_id ."
822
                        WHERE owner_type = '". $owner_type ."'
823
                          AND owner_id = ". $owner_id .
824
                          $_and ."
825
                          AND layout_id = ". $layout_id;
826
                    $res = db_query($sql);
827
                    echo db_error();
828
                }
829
830
831
                //Update ranks
832
                $rank = 0;
833
                $values = array();
834
                foreach($names as $name) {
835
                    $sql = 'UPDATE layouts_contents SET rank = '. ($rank++) ." WHERE owner_type = '". $owner_type ."' AND owner_id = ". $owner_id .' AND column_id = '. $column_id ." AND name = '".$name[1]."' AND content_id = ". $name[0];
836
                    db_query($sql);
837
                    echo db_error();
838
                }
839
            }
840
        }
841
    }
842
843
    /**
844
    * compute the differences between two arrays
845
    */
846
    function _array_diff_names($tab1, $tab2) {
847
        $diff = array();
848
        foreach($tab1 as $e1) {
849
            $found = false;
850
            reset($tab2);
851
            while(!$found && list(,$e2) = each($tab2)) {
852
                $found = !count(array_diff($e1, $e2));
853
            }
854
            if (!$found) {
855
                $diff[] = $e1;
856
            }
857
        }
858
        return $diff;
859
    }
860
}
861
?>
862