3 * Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved
5 * This file is a part of Codendi.
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.
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.
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/>.
21 require_once('common/widget/WidgetLayout.class.php');
22 require_once('common/widget/Widget.class.php');
23 require_once $gfcommon.'include/preplugins.php';
27 * Manage layouts for users, groups and homepage
29 class WidgetLayoutManager {
30 const OWNER_TYPE_USER = 'u';
31 const OWNER_TYPE_GROUP = 'g';
32 const OWNER_TYPE_HOME = 'h';
37 * Display the default layout for the "owner". It my be the home page, the project summary page or /my/ page.
42 function displayLayout($owner_id, $owner_type) {
43 $sql = "SELECT * from owner_layouts where owner_id=$1 and owner_type=$2";
44 $res = db_query_params($sql,array($owner_id,$owner_type));
45 if($res && db_numrows($res)<1) {
46 if($owner_type==self::OWNER_TYPE_USER) {
47 $this->createDefaultLayoutForUser($owner_id);
48 $this->displayLayout($owner_id,$owner_type);
51 $this->createDefaultLayoutForProject($owner_id,1);
52 $this->displayLayout($owner_id,$owner_type);
57 FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = o.layout_id)
58 WHERE o.owner_type = $1
62 $req = db_query_params($sql,array($owner_type,$owner_id));
63 if ($data = db_fetch_array($req)) {
64 $readonly = !$this->_currentUserCanUpdateLayout($owner_id, $owner_type);
66 echo '<p class="customize"><a href="/widgets/widgets.php?owner='. $owner_type.$owner_id .'&layout_id='. $data['id'] .'">'. _("Customize") .'</a></p>';
67 } else if ($owner_type === self::OWNER_TYPE_GROUP) {
70 $layout = new WidgetLayout($data['id'], $data['name'], $data['description'], $data['scope']);
71 $sql = 'SELECT * FROM layouts_rows WHERE layout_id = $1 ORDER BY rank';
72 $req_rows = db_query_params($sql,array($layout->id));
73 while ($data = db_fetch_array($req_rows)) {
74 $row = new WidgetLayout_Row($data['id'], $data['rank']);
75 $sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id = $1';
76 $req_cols = db_query_params($sql,array($row->id));
77 while ($data = db_fetch_array($req_cols)) {
78 $col = new WidgetLayout_Row_Column($data['id'], $data['width']);
79 $sql = "SELECT * FROM layouts_contents WHERE owner_type = $1 AND owner_id = $2 AND column_id = $3 ORDER BY rank";
80 $req_content = db_query_params($sql,array($owner_type, $owner_id, $col->id));
81 while ($data = db_fetch_array($req_content)) {
82 $c = Widget::getInstance($data['name']);
83 if ($c && $c->isAvailable()) {
84 $c->loadContent($data['content_id']);
85 $col->add($c, $data['is_minimized'], $data['display_preferences']);
95 $layout->display($readonly, $owner_id, $owner_type);
101 * _currentUserCanUpdateLayout
103 * @return boolean true if the user dan uppdate the layout (add/remove widget, collapse, set preferences, ...)
107 function _currentUserCanUpdateLayout($owner_id, $owner_type) {
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
116 case self::OWNER_TYPE_GROUP:
117 if (UserManager::instance()->getCurrentUser()->is_super_user==true || user_ismember($request->get('group_id'), 'A')) { //Only project admin
121 case self::OWNER_TYPE_HOME:
130 * createDefaultLayoutForUser
132 * Create the first layout for the user and add some initial widgets:
138 * - MyMonitoredForums
139 * - and widgets of plugins if they want to listen to the event default_widgets_for_new_owner
141 * @param owner_id The id of the newly created user
143 function createDefaultLayoutForUser($owner_id) {
144 $owner_type = self::OWNER_TYPE_USER;
145 $sql = "INSERT INTO owner_layouts(layout_id, is_default, owner_id, owner_type) VALUES (1, 1, $1, $2)";
146 if (db_query_params($sql,array($owner_id,$owner_type))) {
148 $sql = "INSERT INTO layouts_contents(owner_id, owner_type, layout_id, column_id, name, rank) VALUES ";
149 $sql .= "($1, $2, 1, 1, 'myprojects', 0)";
150 $sql .= ",($1, $2, 1, 1, 'mybookmarks', 1)";
151 $sql .= ",($1, $2, 1, 1, 'mymonitoredforums', 2)";
152 $sql .= ",($1, $2, 1, 1, 'mysurveys', 4)";
153 $sql .= ",($1, $2, 1, 2, 'myartifacts', 0)";
154 $sql .= ",($1, $2, 1, 2, 'mymonitoredfp', 1)";
156 /* $em =& EventManager::instance();
158 $em->processEvent('default_widgets_for_new_owner', array('widgets' => &$widgets, 'owner_type' => $owner_type));
159 foreach($widgets as $widget) {
160 $sql .= ",($13, $14, 1, $15, $16, $17)";
162 db_query_params($sql,array($owner_id,$owner_type));
168 * createDefaultLayoutForProject
170 * Create the first layout for a new project, based on its parent template.
171 * Add some widgets based also on its parent configuration and on its service configuration.
173 * @param group_id the id of the newly created project
174 * @param template_id the id of the project template
176 function createDefaultLayoutForProject($group_id, $template_id) {
177 $pm = ProjectManager::instance();
178 $project = $pm->getProject($group_id);
179 $sql = "INSERT INTO owner_layouts(layout_id, is_default, owner_id, owner_type)
180 SELECT layout_id, is_default, $1, owner_type
182 WHERE owner_type = $2
185 if (db_query_params($sql,array($group_id, self::OWNER_TYPE_GROUP,$template_id))) {
186 $sql = "SELECT layout_id, column_id, name, rank, is_minimized, is_removed, display_preferences, content_id
187 FROM layouts_contents
188 WHERE owner_type = $1
191 if ($req = db_query_params($sql,array( self::OWNER_TYPE_GROUP,$template_id))) {
192 while($data = db_fetch_array($req)) {
193 $w = Widget::getInstance($data['name']);
195 $w->setOwner($template_id, self::OWNER_TYPE_GROUP);
196 if ($w->canBeUsedByProject($project)) {
197 $content_id = $w->cloneContent($w->content_id, $group_id, self::OWNER_TYPE_GROUP);
198 $sql = "INSERT INTO layouts_contents(owner_id, owner_type, content_id, layout_id, column_id, name, rank, is_minimized, is_removed, display_preferences)
199 VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);
201 db_query_params($sql,array($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'] ));
212 * displayAvailableWidgets
214 * Display all widget that the user can add to the layout
220 function displayAvailableWidgets($owner_id, $owner_type, $layout_id) {
221 $used_widgets = array();
223 FROM layouts_contents
224 WHERE owner_type = $1
227 AND content_id = 0 AND column_id <> 0";
228 $res = db_query_params($sql,array($owner_type,$owner_id,$layout_id));
229 while($data = db_fetch_array($res)) {
230 $used_widgets[] = $data['name'];
232 echo '<ul class="widget_toolbar">';
233 $url = "/widgets/widgets.php?owner=".HTTPRequest::instance()->get('owner').
234 "&layout_id=".HTTPRequest::instance()->get('layout_id');
236 if ($update_layout = HTTPRequest::instance()->get('update') == 'layout') {
237 echo '<li><a href="'. $url .'">'. _("Add widgets") .'</a></li>';
238 echo '<li class="current"><a href="'. $url.'&update=layout' .'">'. _("Customize layout") .'</a></li>';
241 echo '<li class="current"><a href="'. $url .'">'. _("Add widgets") .'</a></li>';
242 echo '<li><a href="'. $url.'&update=layout' .'">'. _("Customize layout") .'</a></li>';
246 echo '<form action="/widgets/updatelayout.php?owner='. $owner_type.$owner_id .'&action='. $action .'&layout_id='. $layout_id .'" method="post">';
247 if ($update_layout) {
248 $sql = "SELECT * FROM layouts WHERE scope='S' ORDER BY id ";
249 $req_layouts = db_query_params($sql,array());
250 echo '<table cellspacing="0" cellpadding="0">';
252 while ($data = db_fetch_array($req_layouts)) {
253 $checked = $layout_id == $data['id'] ? 'checked="checked"' : '';
254 $is_custom = $is_custom && !$checked;
255 echo '<tr class="layout-manager-chooser '. ($checked ? 'layout-manager-chooser_selected' : '') .'" ><td>';
256 echo '<input type="radio" name="layout_id" value="'. $data['id'] .'" id="layout_'. $data['id'] .'" '. $checked .'/>';
258 echo '<label for="layout_'. $data['id'] .'">';
259 echo html_image('layout/'. strtolower(preg_replace('/(\W+)/', '-', $data['name'])) .'.png', 50, 50, array('alt'=>'layout'));
262 echo '<label for="layout_'. $data['id'] .'"><strong>'. $data['name'] .'</strong><br />';
263 echo $data['description'];
267 /* Custom layout are not available yet */
268 $checked = $is_custom ? 'checked="checked"' : '';
269 echo '<tr class="layout-manager-chooser '. ($checked ? 'layout-manager-chooser_selected' : '') .'"><td>';
270 echo '<input type="radio" name="layout_id" value="-1" id="layout_custom" '. $checked .'/>';
272 echo '<label for="layout_custom">';
273 echo html_image('layout/custom.png', 50, 50, array('style' => 'vertical-align:top;float:left;'));
276 echo '<label for="layout_custom"><strong>'. 'Custom' .'</strong><br />';
277 echo 'Define your own layout:';
279 echo '<table id="layout-manager" cellpadding="0" cellspacing="0">
282 <div class="layout-manager-row-add">+</div>';
283 $sql = 'SELECT * FROM layouts_rows WHERE layout_id = $1 ORDER BY rank';
284 $req_rows = db_query_params($sql,array($layout_id));
285 while ($data = db_fetch_array($req_rows)) {
286 echo '<table class="layout-manager-row" cellspacing="5" cellpadding="2" border="0">
288 <td class="layout-manager-column-add">+</td>';
289 $sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id = $1';
290 $req_cols = db_query_params($sql,array($data['id']));
291 while ($data = db_fetch_array($req_cols)) {
292 echo '<td class="layout-manager-column">
293 <div class="layout-manager-column-remove">x</div>
294 <div class="layout-manager-column-width">
295 <input type="text" value="'. $data['width'] .'" autocomplete="off" size="1" maxlength="3" />%
298 <td class="layout-manager-column-add">+</td>';
302 <div class="layout-manager-row-add">+</div>';
309 echo '<input type="submit" id="save" value="'. _("Submit") .'" />';
312 echo '<table cellpadding="0" cellspacing="0">
316 echo '<table cellpadding="2" cellspacing="0">
318 $after .= $this->_displayWidgetsSelectionForm(sprintf(_("%s Widgets"), forge_get_config('forge_name')), Widget::getCodendiWidgets($owner_type), $used_widgets);
322 <td id="widget-content-categ">'. $after .'</td>
330 function updateLayout($owner_id, $owner_type, $layout, $custom_layout) {
332 FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = o.layout_id)
333 WHERE o.owner_type = $1
337 $req = db_query_params($sql,array($owner_type,$owner_id));
338 if ($data = db_fetch_array($req)) {
339 if ($this->_currentUserCanUpdateLayout($owner_id, $owner_type)) {
340 $old_scope = $data['scope'];
341 $old_layout_id = $data['id'];
342 $new_layout_id = null;
343 if ($layout == '-1' && is_array($custom_layout)) {
344 //Create a new layout based on the custom layout structure defined by the user
346 foreach($custom_layout as $widths) {
348 $cols = explode(',', $widths);
349 foreach($cols as $col) {
350 if ($width = (int)$col) {
358 //If the structure contains at least one column, create a new layout
360 $sql = "INSERT INTO layouts(name, description, scope)
361 VALUES ('custom', '', 'P')";
362 if ($res = db_query_params($sql,array())) {
363 if ($new_layout_id = db_insertid($res,'layouts', 'id')) {
364 //Create rows & columns
366 foreach($rows as $cols) {
367 $sql = "INSERT INTO layouts_rows(layout_id, rank)
369 if ($res = db_query_params($sql,array($new_layout_id,$rank++))) {
370 if ($row_id = db_insertid($res,'layouts_rows', 'id')) {
371 foreach($cols as $width) {
372 $sql = "INSERT INTO layouts_rows_columns(layout_row_id, width)
374 db_query_params($sql,array($row_id,$width));
383 $new_layout_id = $layout;
386 if ($new_layout_id) {
387 //Retrieve columns of old layout
388 $old = $this->_retrieveStructureOfLayout($old_layout_id);
390 //Retrieve columns of new layout
391 $new = $this->_retrieveStructureOfLayout($new_layout_id);
393 // Switch content from old columns to new columns
394 $last_new_col_id = null;
395 reset($new['columns']);
396 foreach($old['columns'] as $old_col) {
397 if (list(,$new_col) = each($new['columns'])) {
398 $last_new_col_id = $new_col['id'];
400 $sql = "UPDATE layouts_contents
407 db_query_params($sql,array($new_layout_id,$last_new_col_id,$owner_type,$owner_id,$old_layout_id,$old_col['id']));
409 $sql = "UPDATE owner_layouts
411 WHERE owner_type = $2
414 db_query_params($sql,array($new_layout_id,$owner_type,$owner_id,$old_layout_id));
416 //If the old layout is custom remove it
417 if ($old_scope != 'S') {
418 $structure = $this->_retrieveStructureOfLayout($old_layout_id);
419 foreach($structure['rows'] as $row) {
420 $sql = "DELETE FROM layouts_rows
422 db_query_params($sql,array($row['id']));
423 $sql = "DELETE FROM layouts_rows_columns
424 WHERE layout_row_id = $1";
425 db_query_params($sql,array($row['id']));
427 $sql = "DELETE FROM layouts
429 db_query_params($sql,array($old_layout_id));
435 $this->feedback($owner_id, $owner_type);
438 function _retrieveStructureOfLayout($layout_id) {
439 $structure = array('rows' => array(), 'columns' => array());
440 $sql = 'SELECT * FROM layouts_rows WHERE layout_id = $1 ORDER BY rank';
441 $req_rows = db_query_params($sql,array($layout_id));
442 while ($row = db_fetch_array($req_rows)) {
443 $structure['rows'][] = $row;
444 $sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id =$1 ORDER BY id';
445 $req_cols = db_query_params($sql,array($row['id']));
446 while ($col = db_fetch_array($req_cols)) {
447 $structure['columns'][] = $col;
454 * _displayWidgetsSelectionForm
458 * @param used_widgets
460 function _displayWidgetsSelectionForm($title, $widgets, $used_widgets) {
461 $hp = Codendi_HTMLPurifier::instance();
462 $additionnal_html = '';
463 if (count($widgets)) {
464 echo '<tr><td colspan="2">';
465 $categs = $this->getCategories($widgets);
466 $widget_rows = array();
467 if (count($categs)) {
468 foreach($categs as $c => $ws) {
469 $widget_rows[$c] = '<a class="widget-categ-switcher" href="#widget-categ-'. $c .'"><span>'. str_replace('-',' ', $hp->purify($c, CODENDI_PURIFIER_CONVERT_HTML)) .'</span></a>';
471 uksort($widget_rows, 'strnatcasecmp');
472 echo '<ul id="widget-categories">';
473 foreach($widget_rows as $row) {
474 echo '<li>'. $row .'</li>';
480 foreach($widgets as $widget_name) {
481 if ($widget = Widget::getInstance($widget_name)) {
482 if ($widget->isAvailable()) {
484 $row .= '<td>'. $widget->getTitle() . $widget->getInstallPreferences() .'</td>';
485 $row .= '<td align="right">';
486 if ($widget->isUnique() && in_array($widget_name, $used_widgets)) {
487 $row .= '<em>'. _("Already used") .'</em>';
489 $row .= '<input type="submit" name="name['. $widget_name .'][add]" value="'. _("Add") .'" />';
492 $widget_rows[$widget->getTitle()] = $row;
497 foreach($widget_rows as $row) {
498 echo '<tr class="'. (count($widget_rows) ? '' : util_get_alt_row_color($i++)) .'">'. $row .'</tr>';
501 if (count($categs)) {
502 foreach($categs as $c => $ws) {
504 $widget_rows = array();
505 foreach($ws as $widget_name => $widget) {
507 $row .= '<div class="widget-preview '. $widget->getPreviewCssClass() .'">';
508 $row .= '<strong>'. $widget->getTitle() .'</strong>';
509 $row .= '<p>'. $widget->getDescription() .'</p>';
510 $row .= $widget->getInstallPreferences();
511 $row .= '</div><div style="text-align:right; border-bottom:1px solid #ddd; padding-bottom:10px; margin-bottom:20px;">';
512 if ($widget->isUnique() && in_array($widget_name, $used_widgets)) {
513 $row .= '<em>'. _("Already used") .'</em>';
515 $row .= '<input type="submit" name="name['. $widget_name .'][add]" value="'. _("Add") .'" />';
518 $widget_rows[$widget->getTitle()] = $row;
520 uksort($widget_rows, 'strnatcasecmp');
521 $additionnal_html .= '<div id="widget-categ-'. $c .'"><h4 class="boxtitle">'. $hp->purify($c, CODENDI_PURIFIER_CONVERT_HTML) .'</h4>';
522 foreach($widget_rows as $row) {
523 $additionnal_html .= $row;
525 $additionnal_html .= '</div>';
529 return $additionnal_html;
531 function getCategories($widgets) {
533 foreach($widgets as $widget_name) {
534 if ($widget = Widget::getInstance($widget_name)) {
535 if ($widget->isAvailable()) {
536 $cs = explode(',', $widget->getCategory());
539 if (!isset($categ[$c])) {
540 $categ[$c] = array();
542 $categ[$c][$widget_name] = $widget;
560 function addWidget($owner_id, $owner_type, $layout_id, $name, &$widget, &$request) {
561 //Search for the right column. (The first used)
562 $sql = "SELECT u.column_id AS id
563 FROM layouts_contents AS u
564 LEFT JOIN (SELECT r.rank AS rank, c.id as id
565 FROM layouts_rows AS r INNER JOIN layouts_rows_columns AS c
566 ON (c.layout_row_id = r.id)
567 WHERE r.layout_id = $1) AS col
568 ON (u.column_id = col.id)
569 WHERE u.owner_type = $2
573 ORDER BY col.rank, col.id";
574 $res = db_query_params($sql,array($layout_id,$owner_type,$owner_id,$layout_id));
576 $column_id = db_result($res, 0, 'id');
578 $sql = "SELECT r.rank AS rank, c.id as id
579 FROM layouts_rows AS r
580 INNER JOIN layouts_rows_columns AS c
581 ON (c.layout_row_id = r.id)
582 WHERE r.layout_id = $1
584 $res = db_query_params($sql,array($layout_id));
585 $column_id = db_result($res, 0, 'id');
589 if ($widget->isUnique()) {
590 //unique widgets do not have content_id
593 $content_id = $widget->create($request);
596 //See if it already exists but not used
597 $sql = "SELECT column_id FROM layouts_contents
602 $res = db_query_params($sql,array($owner_type,$owner_id,$layout_id, $name));
604 if (db_numrows($res) && !$widget->isUnique() && db_result($res, 0, 'column_id') == 0) {
606 $sql = "SELECT min(rank) - 1 AS rank FROM layouts_contents WHERE owner_type =$1 AND owner_id = $2 AND layout_id = $3 AND column_id = $4 ";
607 $res = db_query_params($sql,array($owner_type, $owner_id, $layout_id,$column_id));
609 $rank = db_result($res, 0, 'rank');
612 $sql = "UPDATE layouts_contents
613 SET column_id = $1, rank = $2
614 WHERE owner_type = $3
618 $res = db_query_params($sql,array($column_id,$rank,$owner_type, $owner_id,$name, $layout_id));
622 $sql = "INSERT INTO layouts_contents(owner_type, owner_id, layout_id, column_id, name, content_id, rank)
623 SELECT R1.owner_type, R1.owner_id, R1.layout_id, R1.column_id, $1, $2, coalesce(R2.rank, 1) - 1
624 FROM ( SELECT $3::character varying(1) AS owner_type, $4::integer AS owner_id, $5::integer AS layout_id, $6::integer AS column_id ) AS R1
625 LEFT JOIN layouts_contents AS R2 USING ( owner_type, owner_id, layout_id, column_id )
628 $myfile=fopen('/tmp/debug','a');
629 $params = array($name,$content_id,$owner_type,$owner_id,$layout_id,$column_id);
630 fwrite($myfile, $sql." devient:\n");
631 fwrite($myfile, str_replace(array("$1","$2","$3","$4","$5","$6"),$params,$sql));
632 fwrite($myfile, "\n request content=".$request->get('content_id'));
633 db_query_params($sql,array($name,$content_id,$owner_type,$owner_id,$layout_id,$column_id));
636 $this->feedback($owner_id, $owner_type);
639 protected function feedback($owner_id, $owner_type) {
641 if ($owner_type == self::OWNER_TYPE_GROUP) {
642 //retrieve the short name of the project
643 if ($project = ProjectManager::instance()->getProject($owner_id)) {
644 $hp = Codendi_HTMLPurifier::instance();
645 $link = '/projects/'. $hp->purify($project->getUnixName(), CODENDI_PURIFIER_CONVERT_HTML) ;
647 } else if ($owner_type == self::OWNER_TYPE_USER) {
650 $GLOBALS['feedback'] .= vsprintf(_('Your <a href="%s">dashboard</a> has been updated.'), $link);
662 function removeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id, &$widget) {
663 $sql = "DELETE FROM layouts_contents WHERE owner_type =$1 AND owner_id = $2 AND layout_id = $3 AND name = $4 AND content_id = $5";
664 db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
666 $widget->destroy($instance_id);
679 function mimizeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id) {
680 $sql = "UPDATE layouts_contents SET is_minimized = 1 WHERE owner_type = $1 AND owner_id = $2 AND layout_id = $3 AND name = $4 AND content_id = $5";
681 db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
694 function maximizeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id) {
695 $sql = "UPDATE layouts_contents SET is_minimized = 0 WHERE owner_type =$1 AND owner_id =$2 AND layout_id = $3 AND name = $4 AND content_id = $5";
696 db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
701 * displayWidgetPreferences
709 function displayWidgetPreferences($owner_id, $owner_type, $layout_id, $name, $instance_id) {
710 $sql = "UPDATE layouts_contents SET display_preferences = 1, is_minimized = 0 WHERE owner_type = $1 AND owner_id = $2 AND layout_id = $3 AND name = $4 AND content_id = $5";
711 db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
716 * hideWidgetPreferences
724 function hideWidgetPreferences($owner_id, $owner_type, $layout_id, $name, $instance_id) {
725 $sql = "UPDATE layouts_contents SET display_preferences = 0 WHERE owner_type = $1 AND owner_id = $2 AND layout_id = $3 AND name = $4 AND content_id = $5";
726 db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
739 function reorderLayout($owner_id, $owner_type, $layout_id, &$request) {
740 $keys = array_keys($_REQUEST);
741 foreach($keys as $key) {
742 if (preg_match('`widgetlayout_col_\d+`', $key)) {
745 $split = explode('_', $key);
746 $column_id = (int)$split[count($split)-1];
749 foreach($request->get($key) as $name) {
750 list($name, $id) = explode('-', $name);
751 $names[] = array($id, $name);
754 //Compute differences
755 $originals = array();
756 $sql = "SELECT * FROM layouts_contents WHERE owner_type = $1 AND owner_id = $2 AND column_id = $3 ORDER BY rank";
757 $res = db_query_params($sql,array($owner_type, $owner_id, $column_id));
759 while($data = db_fetch_array($res)) {
760 $originals[] = array($data['content_id'], $data['name']);
763 //delete removed contents
764 $deleted_names = $this->_array_diff_names($originals, $names);
765 if (count($deleted_names)) {
767 foreach($deleted_names as $id => $name) {
773 $_and .= " (name = '".$name[1]."' AND content_id = ". $name[0] .") ";
776 $sql = "UPDATE layouts_contents
778 WHERE owner_type = $1
782 $res = db_query_params($sql,array($owner_type, $owner_id, $column_id));
786 //Insert new contents
787 $added_names = $this->_array_diff_names($names, $originals);
788 if (count($added_names)) {
790 foreach($added_names as $name) {
796 $_and .= " (name = '".$name[1]."' AND content_id = ". $name[0] .") ";
799 //old and new column must be part of the same layout
800 $sql = 'UPDATE layouts_contents
802 WHERE owner_type = $2
806 $res = db_query_params($sql,array($column_id,$owner_type,$owner_id,$layout_id));
814 foreach($names as $name) {
815 $sql = 'UPDATE layouts_contents SET rank = $1 WHERE owner_type =$2 AND owner_id = $3 AND column_id = $4 AND name = $5 AND content_id = $6';
816 db_query_params($sql, array($rank++,$owner_type,$owner_id,$column_id,$name[1],$name[0]));
824 * compute the differences between two arrays
826 function _array_diff_names($tab1, $tab2) {
828 foreach($tab1 as $e1) {
831 while(!$found && list(,$e2) = each($tab2)) {
832 $found = !count(array_diff($e1, $e2));