.
*/
require_once('common/widget/WidgetLayout.class.php');
require_once('common/widget/Widget.class.php');
require_once('preplugins.php');
/**
* WidgetLayoutManager
*
* Manage layouts for users, groups and homepage
*/
class WidgetLayoutManager {
const OWNER_TYPE_USER = 'u';
const OWNER_TYPE_GROUP = 'g';
const OWNER_TYPE_HOME = 'h';
/**
* displayLayout
*
* Display the default layout for the "owner". It my be the home page, the project summary page or /my/ page.
*
* @param owner_id
* @param owner_type
*/
function displayLayout($owner_id, $owner_type) {
$sql = "SELECT * from owner_layouts where owner_id=$1 and owner_type=$2";
$res = db_query_params($sql,array($owner_id,$owner_type));
if($res && db_numrows($res)<1) {
if($owner_type==self::OWNER_TYPE_USER) {
$this->createDefaultLayoutForUser($owner_id);
$this->displayLayout($owner_id,$owner_type);
}
else {
$this->createDefaultLayoutForProject($owner_id,1);
$this->displayLayout($owner_id,$owner_type);
}
}
else {
$sql = "SELECT l.*
FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = o.layout_id)
WHERE o.owner_type = $1
AND o.owner_id = $2
AND o.is_default = 1
";
$req = db_query_params($sql,array($owner_type,$owner_id));
if ($data = db_fetch_array($req)) {
$readonly = !$this->_currentUserCanUpdateLayout($owner_id, $owner_type);
if (!$readonly) {
echo '['. _("Customize") .']';
} else if ($owner_type === self::OWNER_TYPE_GROUP) {
echo '
';
}
$layout = new WidgetLayout($data['id'], $data['name'], $data['description'], $data['scope']);
$sql = 'SELECT * FROM layouts_rows WHERE layout_id = $1 ORDER BY rank';
$req_rows = db_query_params($sql,array($layout->id));
while ($data = db_fetch_array($req_rows)) {
$row = new WidgetLayout_Row($data['id'], $data['rank']);
$sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id = $1';
$req_cols = db_query_params($sql,array($row->id));
while ($data = db_fetch_array($req_cols)) {
$col = new WidgetLayout_Row_Column($data['id'], $data['width']);
$sql = "SELECT * FROM layouts_contents WHERE owner_type = $1 AND owner_id = $2 AND column_id = $3 ORDER BY rank";
$req_content = db_query_params($sql,array($owner_type, $owner_id, $col->id));
while ($data = db_fetch_array($req_content)) {
$c = Widget::getInstance($data['name']);
if ($c && $c->isAvailable()) {
$c->loadContent($data['content_id']);
$col->add($c, $data['is_minimized'], $data['display_preferences']);
}
unset($c);
}
$row->add($col);
unset($col);
}
$layout->add($row);
unset($row);
}
$layout->display($readonly, $owner_id, $owner_type);
}
}
}
/**
* _currentUserCanUpdateLayout
*
* @return boolean true if the user dan uppdate the layout (add/remove widget, collapse, set preferences, ...)
* @param owner_id
* @param owner_type
*/
function _currentUserCanUpdateLayout($owner_id, $owner_type) {
$readonly = true;
$request =& HTTPRequest::instance();
switch ($owner_type) {
case self::OWNER_TYPE_USER:
if (user_getid() == $owner_id) { //Current user can only update its own /my/ page
$readonly = false;
}
break;
case self::OWNER_TYPE_GROUP:
if (UserManager::instance()->getCurrentUser()->is_super_user==true || user_ismember($request->get('group_id'), 'A')) { //Only project admin
$readonly = false;
}
break;
case self::OWNER_TYPE_HOME:
//Only site admin
break;
default:
break;
}
return !$readonly;
}
/**
* createDefaultLayoutForUser
*
* Create the first layout for the user and add some initial widgets:
* - MyArtifacts
* - MyProjects
* - MyBookmarks
* - MySurveys
* - MyMonitoredFP
* - MyMonitoredForums
* - and widgets of plugins if they want to listen to the event default_widgets_for_new_owner
*
* @param owner_id The id of the newly created user
*/
function createDefaultLayoutForUser($owner_id) {
$owner_type = self::OWNER_TYPE_USER;
$sql = "INSERT INTO owner_layouts(layout_id, is_default, owner_id, owner_type) VALUES (1, 1, $1, $2)";
if (db_query_params($sql,array($owner_id,$owner_type))) {
$sql = "INSERT INTO layouts_contents(owner_id, owner_type, layout_id, column_id, name, rank) VALUES ";
$sql .= "($1, $2, 1, 1, 'myprojects', 0)";
$sql .= ",($1, $2, 1, 1, 'mybookmarks', 1)";
$sql .= ",($1, $2, 1, 1, 'mymonitoredforums', 2)";
$sql .= ",($1, $2, 1, 1, 'mysurveys', 4)";
$sql .= ",($1, $2, 1, 2, 'myartifacts', 0)";
$sql .= ",($1, $2, 1, 2, 'mymonitoredfp', 1)";
/* $em =& EventManager::instance();
$widgets = array();
$em->processEvent('default_widgets_for_new_owner', array('widgets' => &$widgets, 'owner_type' => $owner_type));
foreach($widgets as $widget) {
$sql .= ",($13, $14, 1, $15, $16, $17)";
}*/
db_query_params($sql,array($owner_id,$owner_type));
}
echo db_error();
}
/**
* createDefaultLayoutForProject
*
* Create the first layout for a new project, based on its parent template.
* Add some widgets based also on its parent configuration and on its service configuration.
*
* @param group_id the id of the newly created project
* @param template_id the id of the project template
*/
function createDefaultLayoutForProject($group_id, $template_id) {
$pm = ProjectManager::instance();
$project = $pm->getProject($group_id);
$sql = "INSERT INTO owner_layouts(layout_id, is_default, owner_id, owner_type)
SELECT layout_id, is_default, $1, owner_type
FROM owner_layouts
WHERE owner_type = $2
AND owner_id = $3
";
if (db_query_params($sql,array($group_id, self::OWNER_TYPE_GROUP,$template_id))) {
$sql = "SELECT layout_id, column_id, name, rank, is_minimized, is_removed, display_preferences, content_id
FROM layouts_contents
WHERE owner_type = $1
AND owner_id = $2
";
if ($req = db_query_params($sql,array( self::OWNER_TYPE_GROUP,$template_id))) {
while($data = db_fetch_array($req)) {
$w = Widget::getInstance($data['name']);
if ($w) {
$w->setOwner($template_id, self::OWNER_TYPE_GROUP);
if ($w->canBeUsedByProject($project)) {
$content_id = $w->cloneContent($w->content_id, $group_id, self::OWNER_TYPE_GROUP);
$sql = "INSERT INTO layouts_contents(owner_id, owner_type, content_id, layout_id, column_id, name, rank, is_minimized, is_removed, display_preferences)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);
";
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'] ));
echo db_error();
}
}
}
}
}
echo db_error();
}
/**
* displayAvailableWidgets
*
* Display all widget that the user can add to the layout
*
* @param owner_id
* @param owner_type
* @param layout_id
*/
function displayAvailableWidgets($owner_id, $owner_type, $layout_id) {
$used_widgets = array();
$sql = "SELECT *
FROM layouts_contents
WHERE owner_type = $1
AND owner_id = $2
AND layout_id = $3
AND content_id = 0 AND column_id <> 0";
$res = db_query_params($sql,array($owner_type,$owner_id,$layout_id));
while($data = db_fetch_array($res)) {
$used_widgets[] = $data['name'];
}
echo '
';
echo '';
}
function updateLayout($owner_id, $owner_type, $layout, $custom_layout) {
$sql = "SELECT l.*
FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = o.layout_id)
WHERE o.owner_type = $1
AND o.owner_id = $2
AND o.is_default = 1
";
$req = db_query_params($sql,array($owner_type,$owner_id));
if ($data = db_fetch_array($req)) {
if ($this->_currentUserCanUpdateLayout($owner_id, $owner_type)) {
$old_scope = $data['scope'];
$old_layout_id = $data['id'];
$new_layout_id = null;
if ($layout == '-1' && is_array($custom_layout)) {
//Create a new layout based on the custom layout structure defined by the user
$rows = array();
foreach($custom_layout as $widths) {
$row = array();
$cols = explode(',', $widths);
foreach($cols as $col) {
if ($width = (int)$col) {
$row[] = $width;
}
}
if (count($row)) {
$rows[] = $row;
}
}
//If the structure contains at least one column, create a new layout
if (count($rows)) {
$sql = "INSERT INTO layouts(name, description, scope)
VALUES ('custom', '', 'P')";
if ($res = db_query_params($sql,array())) {
if ($new_layout_id = db_insertid($res,'layouts', 'id')) {
//Create rows & columns
$rank = 0;
foreach($rows as $cols) {
$sql = "INSERT INTO layouts_rows(layout_id, rank)
VALUES ($1,$2)";
if ($res = db_query_params($sql,array($new_layout_id,$rank++))) {
if ($row_id = db_insertid($res,'layouts_rows', 'id')) {
foreach($cols as $width) {
$sql = "INSERT INTO layouts_rows_columns(layout_row_id, width)
VALUES ($1,$2)";
db_query_params($sql,array($row_id,$width));
}
}
}
}
}
}
}
} else {
$new_layout_id = $layout;
}
if ($new_layout_id) {
//Retrieve columns of old layout
$old = $this->_retrieveStructureOfLayout($old_layout_id);
//Retrieve columns of new layout
$new = $this->_retrieveStructureOfLayout($new_layout_id);
// Switch content from old columns to new columns
$last_new_col_id = null;
reset($new['columns']);
foreach($old['columns'] as $old_col) {
if (list(,$new_col) = each($new['columns'])) {
$last_new_col_id = $new_col['id'];
}
$sql = "UPDATE layouts_contents
SET layout_id = $1
, column_id =$2
WHERE owner_type =$3
AND owner_id =$4
AND layout_id =$5
AND column_id =$6;";
db_query_params($sql,array($new_layout_id,$last_new_col_id,$owner_type,$owner_id,$old_layout_id,$old_col['id']));
}
$sql = "UPDATE owner_layouts
SET layout_id = $1
WHERE owner_type = $2
AND owner_id = $3
AND layout_id = $4";
db_query_params($sql,array($new_layout_id,$owner_type,$owner_id,$old_layout_id));
//If the old layout is custom remove it
if ($old_scope != 'S') {
$structure = $this->_retrieveStructureOfLayout($old_layout_id);
foreach($structure['rows'] as $row) {
$sql = "DELETE FROM layouts_rows
WHERE id = $1";
db_query_params($sql,array($row['id']));
$sql = "DELETE FROM layouts_rows_columns
WHERE layout_row_id = $1";
db_query_params($sql,array($row['id']));
}
$sql = "DELETE FROM layouts
WHERE id = $1";
db_query_params($sql,array($old_layout_id));
}
}
}
}
$this->feedback($owner_id, $owner_type);
}
function _retrieveStructureOfLayout($layout_id) {
$structure = array('rows' => array(), 'columns' => array());
$sql = 'SELECT * FROM layouts_rows WHERE layout_id = $1 ORDER BY rank';
$req_rows = db_query_params($sql,array($layout_id));
while ($row = db_fetch_array($req_rows)) {
$structure['rows'][] = $row;
$sql = 'SELECT * FROM layouts_rows_columns WHERE layout_row_id =$1 ORDER BY id';
$req_cols = db_query_params($sql,array($row['id']));
while ($col = db_fetch_array($req_cols)) {
$structure['columns'][] = $col;
}
}
return $structure;
}
/**
* _displayWidgetsSelectionForm
*
* @param title
* @param widgets
* @param used_widgets
*/
function _displayWidgetsSelectionForm($title, $widgets, $used_widgets) {
$hp = Codendi_HTMLPurifier::instance();
$additionnal_html = '';
if (count($widgets)) {
echo '';
$categs = $this->getCategories($widgets);
$widget_rows = array();
if (count($categs)) {
foreach($categs as $c => $ws) {
$widget_rows[$c] = ''. str_replace('-',' ', $hp->purify($c, CODENDI_PURIFIER_CONVERT_HTML)) .'';
}
uksort($widget_rows, 'strnatcasecmp');
echo '';
echo ' |
';
} else {
echo '';
foreach($widgets as $widget_name) {
if ($widget = Widget::getInstance($widget_name)) {
if ($widget->isAvailable()) {
$row = '';
$row .= ''. $widget->getTitle() . $widget->getInstallPreferences() .' | ';
$row .= '';
if ($widget->isUnique() && in_array($widget_name, $used_widgets)) {
$row .= ''. _("Already used") .'';
} else {
$row .= '';
}
$row .= ' | ';
$widget_rows[$widget->getTitle()] = $row;
}
}
}
$i = 0;
foreach($widget_rows as $row) {
echo ''. $row .'
';
}
}
if (count($categs)) {
foreach($categs as $c => $ws) {
$i = 0;
$widget_rows = array();
foreach($ws as $widget_name => $widget) {
$row = '';
$row .= '';
if ($widget->isUnique() && in_array($widget_name, $used_widgets)) {
$row .= ''. _("Already used") .'';
} else {
$row .= '';
}
$row .= '
';
$widget_rows[$widget->getTitle()] = $row;
}
uksort($widget_rows, 'strnatcasecmp');
$additionnal_html .= ''. $hp->purify($c, CODENDI_PURIFIER_CONVERT_HTML) .'
';
foreach($widget_rows as $row) {
$additionnal_html .= $row;
}
$additionnal_html .= '';
}
}
}
return $additionnal_html;
}
function getCategories($widgets) {
$categ = array();
foreach($widgets as $widget_name) {
if ($widget = Widget::getInstance($widget_name)) {
if ($widget->isAvailable()) {
$cs = explode(',', $widget->getCategory());
foreach($cs as $c) {
if ($c = trim($c)) {
if (!isset($categ[$c])) {
$categ[$c] = array();
}
$categ[$c][$widget_name] = $widget;
}
}
}
}
}
return $categ;
}
/**
* addWidget
*
* @param owner_id
* @param owner_type
* @param layout_id
* @param name
* @param widget
* @param request
*/
function addWidget($owner_id, $owner_type, $layout_id, $name, &$widget, &$request) {
//Search for the right column. (The first used)
$sql = "SELECT u.column_id AS id
FROM layouts_contents AS u
LEFT JOIN (SELECT r.rank AS rank, c.id as id
FROM layouts_rows AS r INNER JOIN layouts_rows_columns AS c
ON (c.layout_row_id = r.id)
WHERE r.layout_id = $1) AS col
ON (u.column_id = col.id)
WHERE u.owner_type = $2
AND u.owner_id = $3
AND u.layout_id = $4
AND u.column_id <> 0
ORDER BY col.rank, col.id";
$res = db_query_params($sql,array($layout_id,$owner_type,$owner_id,$layout_id));
echo db_error();
$column_id = db_result($res, 0, 'id');
if (!$column_id) {
$sql = "SELECT r.rank AS rank, c.id as id
FROM layouts_rows AS r
INNER JOIN layouts_rows_columns AS c
ON (c.layout_row_id = r.id)
WHERE r.layout_id = $1
ORDER BY rank, id";
$res = db_query_params($sql,array($layout_id));
$column_id = db_result($res, 0, 'id');
}
//content_id
if ($widget->isUnique()) {
//unique widgets do not have content_id
$content_id = 0;
} else {
$content_id = $widget->create($request);
}
//See if it already exists but not used
$sql = "SELECT column_id FROM layouts_contents
WHERE owner_type =$1
AND owner_id = $2
AND layout_id = $3
AND name = $4";
$res = db_query_params($sql,array($owner_type,$owner_id,$layout_id, $name));
echo db_error();
if (db_numrows($res) && !$widget->isUnique() && db_result($res, 0, 'column_id') == 0) {
//search for rank
$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 ";
$res = db_query_params($sql,array($owner_type, $owner_id, $layout_id,$column_id));
echo db_error();
$rank = db_result($res, 0, 'rank');
//Update
$sql = "UPDATE layouts_contents
SET column_id = $1, rank = $2
WHERE owner_type = $3
AND owner_id = $4
AND name = $5
AND layout_id = $6";
$res = db_query_params($sql,array($column_id,$rank,$owner_type, $owner_id,$name, $layout_id));
echo db_error();
} else {
//Insert
$sql = "INSERT INTO layouts_contents(owner_type, owner_id, layout_id, column_id, name, content_id, rank)
SELECT R1.owner_type, R1.owner_id, R1.layout_id, R1.column_id, $1, $2, coalesce(R2.rank, 1) - 1
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
LEFT JOIN layouts_contents AS R2 USING ( owner_type, owner_id, layout_id, column_id )
ORDER BY rank ASC
LIMIT 1";
$myfile=fopen('/tmp/debug','a');
$params = array($name,$content_id,$owner_type,$owner_id,$layout_id,$column_id);
fwrite($myfile, $sql." devient:\n");
fwrite($myfile, str_replace(array("$1","$2","$3","$4","$5","$6"),$params,$sql));
fwrite($myfile, "\n request content=".$request->get('content_id'));
db_query_params($sql,array($name,$content_id,$owner_type,$owner_id,$layout_id,$column_id));
echo db_error();
}
$this->feedback($owner_id, $owner_type);
}
protected function feedback($owner_id, $owner_type) {
$link = '/';
if ($owner_type == self::OWNER_TYPE_GROUP) {
//retrieve the short name of the project
if ($project = ProjectManager::instance()->getProject($owner_id)) {
$hp = Codendi_HTMLPurifier::instance();
$link = '/projects/'. $hp->purify($project->getUnixName(), CODENDI_PURIFIER_CONVERT_HTML) ;
}
} else if ($owner_type == self::OWNER_TYPE_USER) {
$link = '/my/';
}
$GLOBALS['feedback'] .= vsprintf(_('Your dashboard has been updated.'), $link);
}
/**
* removeWidget
*
* @param owner_id
* @param owner_type
* @param layout_id
* @param name
* @param instance_id
*/
function removeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id, &$widget) {
$sql = "DELETE FROM layouts_contents WHERE owner_type =$1 AND owner_id = $2 AND layout_id = $3 AND name = $4 AND content_id = $5";
db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
if (!db_error()) {
$widget->destroy($instance_id);
}
}
/**
* mimizeWidget
*
* @param owner_id
* @param owner_type
* @param layout_id
* @param name
* @param instance_id
*/
function mimizeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id) {
$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";
db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
echo db_error();
}
/**
* maximizeWidget
*
* @param owner_id
* @param owner_type
* @param layout_id
* @param name
* @param instance_id
*/
function maximizeWidget($owner_id, $owner_type, $layout_id, $name, $instance_id) {
$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";
db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
echo db_error();
}
/**
* displayWidgetPreferences
*
* @param owner_id
* @param owner_type
* @param layout_id
* @param name
* @param instance_id
*/
function displayWidgetPreferences($owner_id, $owner_type, $layout_id, $name, $instance_id) {
$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";
db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
echo db_error();
}
/**
* hideWidgetPreferences
*
* @param owner_id
* @param owner_type
* @param layout_id
* @param name
* @param instance_id
*/
function hideWidgetPreferences($owner_id, $owner_type, $layout_id, $name, $instance_id) {
$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";
db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
echo db_error();
}
/**
* reorderLayout
*
* @param owner_id
* @param owner_type
* @param layout_id
* @param name
* @param instance_id
*/
function reorderLayout($owner_id, $owner_type, $layout_id, &$request) {
$keys = array_keys($_REQUEST);
foreach($keys as $key) {
if (preg_match('`widgetlayout_col_\d+`', $key)) {
$split = explode('_', $key);
$column_id = (int)$split[count($split)-1];
$names = array();
foreach($request->get($key) as $name) {
list($name, $id) = explode('-', $name);
$names[] = array($id, $name);
}
//Compute differences
$originals = array();
$sql = "SELECT * FROM layouts_contents WHERE owner_type = $1 AND owner_id = $2 AND column_id = $3 ORDER BY rank";
$res = db_query_params($sql,array($owner_type, $owner_id, $column_id));
echo db_error();
while($data = db_fetch_array($res)) {
$originals[] = array($data['content_id'], $data['name']);
}
//delete removed contents
$deleted_names = $this->_array_diff_names($originals, $names);
if (count($deleted_names)) {
$_and = '';
foreach($deleted_names as $id => $name) {
if ($_and) {
$_and .= ' OR ';
} else {
$_and .= ' AND (';
}
$_and .= " (name = '".$name[1]."' AND content_id = ". $name[0] .") ";
}
$_and .= ')';
$sql = "UPDATE layouts_contents
SET column_id = 0
WHERE owner_type = $1
AND owner_id = $2
AND column_id = $3".
$_and;
$res = db_query_params($sql,array($owner_type, $owner_id, $column_id));
echo db_error();
}
//Insert new contents
$added_names = $this->_array_diff_names($names, $originals);
if (count($added_names)) {
$_and = '';
foreach($added_names as $name) {
if ($_and) {
$_and .= ' OR ';
} else {
$_and .= ' AND (';
}
$_and .= " (name = '".$name[1]."' AND content_id = ". $name[0] .") ";
}
$_and .= ')';
//old and new column must be part of the same layout
$sql = 'UPDATE layouts_contents
SET column_id = $1
WHERE owner_type = $2
AND owner_id = $3' .
$_and ."
AND layout_id = $4";
$res = db_query_params($sql,array($column_id,$owner_type,$owner_id,$layout_id));
echo db_error();
}
//Update ranks
$rank = 0;
$values = array();
foreach($names as $name) {
$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';
db_query_params($sql, array($rank++,$owner_type,$owner_id,$column_id,$name[1],$name[0]));
echo db_error();
}
}
}
}
/**
* compute the differences between two arrays
*/
function _array_diff_names($tab1, $tab2) {
$diff = array();
foreach($tab1 as $e1) {
$found = false;
reset($tab2);
while(!$found && list(,$e2) = each($tab2)) {
$found = !count(array_diff($e1, $e2));
}
if (!$found) {
$diff[] = $e1;
}
}
return $diff;
}
}
?>