[Fusionforge-commits] r9702 - in trunk/plugins/coclico: . codendi-specific codendi-specific/common codendi-specific/common/dao codendi-specific/common/dao/include codendi-specific/www codendi-specific/www/include

Mélanie Le Bail melanelebail at libremir.placard.fr.eu.org
Mon May 10 14:01:16 CEST 2010


Author: melanelebail
Date: 2010-05-10 14:01:16 +0200 (Mon, 10 May 2010)
New Revision: 9702

Added:
   trunk/plugins/coclico/codendi-specific/
   trunk/plugins/coclico/codendi-specific/common/
   trunk/plugins/coclico/codendi-specific/common/dao/
   trunk/plugins/coclico/codendi-specific/common/dao/include/
   trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php
   trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php.orig
   trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php
   trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php.orig
   trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccess
   trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccessObject
   trunk/plugins/coclico/codendi-specific/env.inc.php
   trunk/plugins/coclico/codendi-specific/plugins_utils.php~
   trunk/plugins/coclico/codendi-specific/www/
   trunk/plugins/coclico/codendi-specific/www/include/
   trunk/plugins/coclico/codendi-specific/www/include/plugins_utils.php
Log:
Add codendi specific changes to work with coclico plugins


Added: trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php
===================================================================
--- trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved
+ *
+ * This file is a part of Codendi.
+ *
+ * Codendi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Codendi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once('DataAccessResult.class.php');
+require_once('DataAccessException.class.php');
+
+$GLOBALS['DEBUG_DAO_QUERY_COUNT'] = 0;
+
+if(!defined('CODENDI_DB_NULL')) define('CODENDI_DB_NULL', 0);
+if(!defined('CODENDI_DB_NOT_NULL')) define('CODENDI_DB_NOT_NULL', 1);
+
+/**
+ *  A simple class for querying MySQL
+ */
+class DataAccess {
+    /**
+    * @access protected
+    * $db stores a database resource
+    */
+    var $db;
+    
+    /**
+     * store the database name used to instantiate the connection
+     */
+    public $db_name;
+    
+    /**
+    * Constucts a new DataAccess object
+    * @param $host string hostname for dbserver
+    * @param $user string dbserver user
+    * @param $pass string dbserver user password
+    * @param $db string database name
+    */
+    function DataAccess($host,$user,$pass,$db,$opt=0) {
+        $this->store = array();
+        $this->db = $this->connect($host, $user, $pass, $opt);
+        if ($this->db) {
+            mysql_query("SET NAMES 'utf8'", $this->db);
+            if (!mysql_select_db($db,$this->db)) {
+                trigger_error(mysql_error(), E_USER_ERROR);
+            }
+            $this->db_name = $db;
+        } else {
+            throw new DataAccessException('Unable to access the database. Please contact your administrator.');
+        }
+    }
+    
+    protected function connect($host, $user, $pass, $opt) {
+        return mysql_connect($host, $user, $pass, true, $opt);
+    }
+    
+    var $store;
+    
+    /**
+    * Fetches a query resources and stores it in a local member
+    * @param $sql string the database query to run
+    * @return object DataAccessResult
+    */
+    function &fetch($sql,$params=array()) {
+        $time = microtime(1);
+        $res = $this->mysql_query_params($sql,$params,$this->db);
+        if (isset($GLOBALS['DEBUG_MODE']) && $GLOBALS['DEBUG_MODE']) {
+            $GLOBALS['DEBUG_DAO_QUERY_COUNT']++;
+            $GLOBALS['QUERIES'][]=$sql;
+            if (!isset($GLOBALS['DBSTORE'][md5($sql)])) {
+                $GLOBALS['DBSTORE'][md5($sql)] = array('sql' => $sql, 'nb' => 0, 'trace' => array());
+            }
+            $GLOBALS['DBSTORE'][md5($sql)]['trace'][$GLOBALS['DBSTORE'][md5($sql)]['nb']++] = array(debug_backtrace(), $time, microtime(1));
+        }
+        $dar = new DataAccessResult($this, $res);
+        return $dar;
+    }
+
+    /**
+     * Return ID generated from the previous INSERT operation.
+     *
+     * @return int, or 0 if the previous query does not generate an AUTO_INCREMENT value, or FALSE if no MySQL connection was established
+     */
+    function lastInsertId() {
+        if($this->db) {
+            return mysql_insert_id($this->db);
+        } else {
+            return mysql_insert_id();
+        }
+    }
+
+    /**
+     * Return number of rows affected by the last INSERT, UPDATE or DELETE.
+     *
+     * @return int
+     */
+    function affectedRows() {
+        if($this->db) {
+            return mysql_affected_rows($this->db);
+        } else {
+            return mysql_affected_rows();
+        }
+    }
+
+    /**
+    * Returns any MySQL errors
+    * @return string a MySQL error
+    */
+    function isError() {
+        if ($this->db) {
+            return mysql_error($this->db);
+        } else {
+            return mysql_error();
+        }
+    }
+    
+    /**
+    * Quote variable to make safe
+    * @see http://php.net/mysql-real-escape-string
+    * @static
+    */
+    function quoteSmart($value, $params = array()) {
+        // Quote if not integer
+        if ($this->db) {
+            $value = mysql_real_escape_string($value, $this->db);
+        } else {
+            $value = mysql_escape_string($value);
+        }
+        if (!is_numeric($value) || (isset($params['force_string']) && $params['force_string'])) {
+            $value = "'" . $value . "'";
+        }
+        return $value;
+    }
+
+    /**
+     * Safe implode function to use with SQL queries
+     * @static
+     */
+    function quoteSmartImplode($glue, $pieces, $params = array()) {
+        $lem = array_keys($pieces);
+        $str='';
+        $after_first=false;
+        foreach ($pieces as $piece) {
+            if ($after_first) {
+                $str.=$glue;
+            }
+            $str.=$this->quoteSmart($piece,$params);
+            $after_first=true;
+        }            
+        return $str;
+    }
+    
+
+    function escapeInt($v, $null = CODENDI_DB_NOT_NULL) {
+        $m = array();
+        if($null === CODENDI_DB_NULL && $v === '') {
+            return 'NULL';
+        }
+        if(preg_match('/^([+-]?[1-9][0-9]*|[+-]?0)$/', $v, $m)) {
+            return $m[1];
+        }
+        return '0';
+    }
+
+   # Parameterised query implementation for MySQL (similar PostgreSQL's PHP function pg_query_params)
+   # Example: mysql_query_params( "SELECT * FROM my_table WHERE col1=$1 AND col2=$2", array( 42, "It's ok" ) );
+    function mysql_query_params($sql,$params=array(),$database) {
+	if(!empty($params)) {
+		for ($i=1;$i<=count($params);$i++ ) {
+	   		$args[]="$".$i;	
+		}
+		return mysql_query(str_replace($args,$params,$sql),$database);
+	} else {
+		return mysql_query($sql,$database);
+	}
+	
+    }
+
+
+
+
+}
+?>

Added: trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php.orig
===================================================================
--- trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php.orig	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccess.class.php.orig	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,178 @@
+<?php
+/**
+ * Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved
+ *
+ * This file is a part of Codendi.
+ *
+ * Codendi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Codendi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Codendi. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once('DataAccessResult.class.php');
+require_once('DataAccessException.class.php');
+
+$GLOBALS['DEBUG_DAO_QUERY_COUNT'] = 0;
+
+if(!defined('CODENDI_DB_NULL')) define('CODENDI_DB_NULL', 0);
+if(!defined('CODENDI_DB_NOT_NULL')) define('CODENDI_DB_NOT_NULL', 1);
+
+/**
+ *  A simple class for querying MySQL
+ */
+class DataAccess {
+    /**
+    * @access protected
+    * $db stores a database resource
+    */
+    var $db;
+    
+    /**
+     * store the database name used to instantiate the connection
+     */
+    public $db_name;
+    
+    /**
+    * Constucts a new DataAccess object
+    * @param $host string hostname for dbserver
+    * @param $user string dbserver user
+    * @param $pass string dbserver user password
+    * @param $db string database name
+    */
+    function DataAccess($host,$user,$pass,$db,$opt=0) {
+        $this->store = array();
+        $this->db = $this->connect($host, $user, $pass, $opt);
+        if ($this->db) {
+            mysql_query("SET NAMES 'utf8'", $this->db);
+            if (!mysql_select_db($db,$this->db)) {
+                trigger_error(mysql_error(), E_USER_ERROR);
+            }
+            $this->db_name = $db;
+        } else {
+            throw new DataAccessException('Unable to access the database. Please contact your administrator.');
+        }
+    }
+    
+    protected function connect($host, $user, $pass, $opt) {
+        return mysql_connect($host, $user, $pass, true, $opt);
+    }
+    
+    var $store;
+    
+    /**
+    * Fetches a query resources and stores it in a local member
+    * @param $sql string the database query to run
+    * @return object DataAccessResult
+    */
+    function &fetch($sql) {
+        $time = microtime(1);
+        $res = mysql_query($sql,$this->db);
+        if (isset($GLOBALS['DEBUG_MODE']) && $GLOBALS['DEBUG_MODE']) {
+            $GLOBALS['DEBUG_DAO_QUERY_COUNT']++;
+            $GLOBALS['QUERIES'][]=$sql;
+            if (!isset($GLOBALS['DBSTORE'][md5($sql)])) {
+                $GLOBALS['DBSTORE'][md5($sql)] = array('sql' => $sql, 'nb' => 0, 'trace' => array());
+            }
+            $GLOBALS['DBSTORE'][md5($sql)]['trace'][$GLOBALS['DBSTORE'][md5($sql)]['nb']++] = array(debug_backtrace(), $time, microtime(1));
+        }
+        $dar = new DataAccessResult($this, $res);
+        return $dar;
+    }
+
+    /**
+     * Return ID generated from the previous INSERT operation.
+     *
+     * @return int, or 0 if the previous query does not generate an AUTO_INCREMENT value, or FALSE if no MySQL connection was established
+     */
+    function lastInsertId() {
+        if($this->db) {
+            return mysql_insert_id($this->db);
+        } else {
+            return mysql_insert_id();
+        }
+    }
+
+    /**
+     * Return number of rows affected by the last INSERT, UPDATE or DELETE.
+     *
+     * @return int
+     */
+    function affectedRows() {
+        if($this->db) {
+            return mysql_affected_rows($this->db);
+        } else {
+            return mysql_affected_rows();
+        }
+    }
+
+    /**
+    * Returns any MySQL errors
+    * @return string a MySQL error
+    */
+    function isError() {
+        if ($this->db) {
+            return mysql_error($this->db);
+        } else {
+            return mysql_error();
+        }
+    }
+    
+    /**
+    * Quote variable to make safe
+    * @see http://php.net/mysql-real-escape-string
+    * @static
+    */
+    function quoteSmart($value, $params = array()) {
+        // Quote if not integer
+        if ($this->db) {
+            $value = mysql_real_escape_string($value, $this->db);
+        } else {
+            $value = mysql_escape_string($value);
+        }
+        if (!is_numeric($value) || (isset($params['force_string']) && $params['force_string'])) {
+            $value = "'" . $value . "'";
+        }
+        return $value;
+    }
+
+    /**
+     * Safe implode function to use with SQL queries
+     * @static
+     */
+    function quoteSmartImplode($glue, $pieces, $params = array()) {
+        $lem = array_keys($pieces);
+        $str='';
+        $after_first=false;
+        foreach ($pieces as $piece) {
+            if ($after_first) {
+                $str.=$glue;
+            }
+            $str.=$this->quoteSmart($piece,$params);
+            $after_first=true;
+        }            
+        return $str;
+    }
+    
+
+    function escapeInt($v, $null = CODENDI_DB_NOT_NULL) {
+        $m = array();
+        if($null === CODENDI_DB_NULL && $v === '') {
+            return 'NULL';
+        }
+        if(preg_match('/^([+-]?[1-9][0-9]*|[+-]?0)$/', $v, $m)) {
+            return $m[1];
+        }
+        return '0';
+    }
+
+}
+?>

Added: trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php
===================================================================
--- trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,241 @@
+<?php
+/**
+ *  Base class for data access objects
+ */
+class DataAccessObject {
+    /**
+    * Private
+    * $da stores data access object
+    */
+    var $da;
+
+    //! A constructor
+    /**
+    * Constructs the Dao
+    * @param $da instance of the DataAccess class
+    */
+    function DataAccessObject( & $da ) {
+        $this->table_name = 'CLASSNAME_MUST_BE_DEFINE_FOR_EACH_CLASS';
+        //Dynamic table_name guessing does not work (at least in php4)
+        //because classname are lowercase only :(
+        /*
+        $s = get_class($this);
+        $this->table_name = '';
+        $len = strlen($s);
+        for($i = 1 ; $i <= $len ; ++$i) {
+            if ($i < $len && preg_match('`[A-Z]`', $s[$i - 1]) && preg_match('`[a-z]`', $s[$i])) {
+                $this->table_name .= '_';
+            }
+            $this->table_name .= strtolower($s[$i - 1]);
+        }
+        */
+        $this->da=$da;
+    }
+
+    //! An accessor
+    /**
+    * For SELECT queries
+    * @param $sql the query string
+    * @return mixed either false if error or object DataAccessResult
+    */
+    function &retrieve($sql,$params=array()) {
+        $result =& $this->da->fetch($sql,$params);
+        if ($error = $result->isError()) {
+            $trace = debug_backtrace();
+            $i = isset($trace[1]) ? 1 : 0;
+            trigger_error($error .' ==> '. $sql ." @@ ". $trace[$i]['file'] .' at line '. $trace[$i]['line']);
+            $result = false;
+        }
+        return $result;
+    }
+
+    //! An accessor
+    /**
+    * For INSERT, UPDATE and DELETE queries
+    * @param $sql the query string
+    * @return boolean true if success
+    */
+    function update($sql,$params=array()) {
+        $result = $this->da->fetch($sql,$params);
+        if ($error = $result->isError()) {
+            $trace = debug_backtrace();
+            $i = isset($trace[1]) ? 1 : 0;
+            trigger_error($error .' ==> '. $sql ." @@ ". $trace[$i]['file'] .' at line '. $trace[$i]['line']);
+            return false;
+        } else {
+            return true;
+        }
+    }
+    
+    /**
+    * Prepare ranking of items.
+    * 
+    * @see  https://partners.xrce.xerox.com/plugins/docman/?group_id=120&action=show&id=95
+    * 
+    * @param   int $id  The id of the item to rank. 0 if the item doesn't exist.
+    * @param   int $parent_id   The id of the element used to group items
+    * @param   mixed $rank    The rank asked for the items. Possible values are :
+    *                       '--'        => do not change the rank
+    *                       'beginning' => to put item before each others
+    *                       'end'       => to put item after each others
+    *                       'up'        => to put item before previous sibling
+    *                       'down'      => to put item after next sibling
+    *                       <int>       => to put item at a specific position. 
+    *                   Please note that for a new item ($id = 0) you must not use
+    *                   '--', 'up' or 'down' value
+    * @param   string $primary_key the column name of the primary key. Default 'id'
+    * @param   string $parent_key the column key used to groups items. Default 'parent_id'
+    * @param   string $rank_key the column key used to rank items. Default 'rank'
+    * @return  mixed false if there is no rank to update of the numerical
+    *          value of the new rank of the item. If return 'null' it means
+    *          that sth wrong happended.
+    */
+    function prepareRanking($id, $parent_id, $rank, $primary_key = 'id', $parent_key = 'parent_id', $rank_key = 'rank') {
+        $newRank = null;
+        
+        // First, check if there is already some items
+        $sql = sprintf('SELECT NULL'.
+                       ' FROM '. $this->table_name .
+                       ' WHERE '. $parent_key .' = %d',
+                       $parent_id);
+        $dar = $this->retrieve($sql);
+        if($dar && !$dar->isError() && $dar->rowCount() == 0) {
+            // No items: nice, just set the first one to 0.
+            $newRank = 0;
+        }
+        else {
+            switch((string)$rank) {
+            case '--':
+                $sql = sprintf('SELECT '. $rank_key .
+                               ' FROM '. $this->table_name .
+                               ' WHERE '. $primary_key .' = %d',
+                               (int)$id);
+                $dar = $this->retrieve($sql);
+                if($dar && !$dar->isError() && $dar->rowCount() == 1) {
+                    $row = $dar->current();
+                    $newRank = $row[$rank_key];
+                }
+                break;
+            case 'end':
+                // Simple case: just pickup the most high rank in the table
+                // and add 1 to be laster than the first.
+                $sql = sprintf('SELECT MAX('. $rank_key .')+1 as '. $rank_key .
+                               ' FROM '. $this->table_name .
+                               ' WHERE '. $parent_key .' = %d',
+                               $parent_id);
+                $dar = $this->retrieve($sql);
+                if($dar && !$dar->isError() && $dar->rowCount() == 1) {
+                    $row = $dar->current();
+                    $newRank = $row[$rank_key];
+                }
+                break;
+
+            case 'up':
+            case 'down':
+                // Those 2 cases are quite complex and are only mandatory if
+                // you want to 'Move up' or 'Move down' an item. If you can
+                // only select in a select box you can remove this part of
+                // the code.
+
+                // The general idea here is: we want to move up (or down) an
+                // item but we only know it's id and the sens (up/down) of the
+                // slide. Our goal is to exchange the rank value of the item
+                // behind (in case of up) with the current one.
+
+                // This is done in 2 steps:
+                // * first fetch the item_id and the rank of the item we want
+                //   to stole the place.
+                // * then exchange the 2 rank values.
+
+                if ($rank == 'down') {
+                    $op    = '>';
+                    $order = 'ASC';
+                } else {
+                    $op    = '<';
+                    $order = 'DESC';
+                }
+
+                // This SQL query aims to get the item_id and the rank of the item
+                // Just behind us (for 'up' case).
+                // In your implementation, USING(parent_id) should refer to the field
+                // that group all the items in one list.
+                $sql = sprintf('SELECT i1.'. $primary_key .' as id, i1.'. $rank_key .' as '. $rank_key .
+                                   ' FROM '. $this->table_name .' i1'.
+                                   '  INNER JOIN '. $this->table_name .' i2 USING('. $parent_key .')'.
+                                   ' WHERE i2.'. $primary_key .' = %d'.
+                                   '   AND i1.'. $parent_key .' = %d'.
+                                   '   AND i1.'. $rank_key .' %s i2.'. $rank_key .
+                                   ' ORDER BY i1.'. $rank_key .' %s'.
+                                   ' LIMIT 1',
+                                   $id,
+                                   $parent_id,
+                                   $op,
+                                   $order);
+                $dar = $this->retrieve($sql);
+                if ($dar && !$dar->isError() && $dar->rowCount() == 1) {
+                    $row = $dar->current();
+                    // This query exchange the two values.
+                    // Warning: the order is very important, please check that
+                    // your final query work as expected.
+                    $sql = sprintf('UPDATE '. $this->table_name .' i1, '. $this->table_name .' i2'.
+                                   ' SET i1.'. $rank_key .' = i2.'. $rank_key .', i2.'. $rank_key .' = %d'.
+                                   ' WHERE i1.'. $primary_key .' = %d '.
+                                   '  AND i2.'. $primary_key .' = %d',
+                                   $row[$rank_key],
+                                   $row['id'],
+                                   $id);
+                    $this->update($sql);
+                    $newRank = false;
+                }
+                break;
+
+            case 'beginning':
+                // This first part is quite simple: just pickup the lower rank
+                // in the table
+                $sql = sprintf('SELECT MIN('. $rank_key .') as '. $rank_key .
+                               ' FROM '. $this->table_name .
+                               ' WHERE '. $parent_key .' = %d',
+                               $parent_id);
+                $dar = $this->retrieve($sql);
+                if($dar && !$dar->isError()) {
+                    $row = $dar->current();
+                    $rank = $row[$rank_key];
+                }
+                // Very important: no break here, because we have to update all
+                // ranks upper:
+                // no break;
+
+            default:
+                // Here $rank is a numerical value that represent the rank after
+                // one item (user selected 'After XXX' in select box).
+                // The idea is to move up all the ranks upper to this value and to
+                // return the current value as the new rank.
+                $sql = sprintf('UPDATE '. $this->table_name .
+                               ' SET '. $rank_key .' = '. $rank_key .' + 1'.
+                               ' WHERE '. $parent_key .' = %d'.
+                               '  AND '. $rank_key .' >= %d',
+                               $parent_id, $rank);
+                $updated = $this->update($sql);
+                if($updated) {
+                    $newRank = $rank;
+                }
+            }
+        }
+        return $newRank;
+    }
+
+    /**
+     * Return the result of 'FOUND_ROWS()' SQL method for the last query.
+     */
+    function foundRows() {
+        $sql = "SELECT FOUND_ROWS() as nb";
+        $dar = $this->retrieve($sql);
+        if($dar && !$dar->isError()) {
+            $row = $dar->getRow();
+            return $row['nb'];
+        } else {
+            return false;
+        }
+    }
+}
+?>

Added: trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php.orig
===================================================================
--- trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php.orig	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/common/dao/include/DataAccessObject.class.php.orig	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,241 @@
+<?php
+/**
+ *  Base class for data access objects
+ */
+class DataAccessObject {
+    /**
+    * Private
+    * $da stores data access object
+    */
+    var $da;
+
+    //! A constructor
+    /**
+    * Constructs the Dao
+    * @param $da instance of the DataAccess class
+    */
+    function DataAccessObject( & $da ) {
+        $this->table_name = 'CLASSNAME_MUST_BE_DEFINE_FOR_EACH_CLASS';
+        //Dynamic table_name guessing does not work (at least in php4)
+        //because classname are lowercase only :(
+        /*
+        $s = get_class($this);
+        $this->table_name = '';
+        $len = strlen($s);
+        for($i = 1 ; $i <= $len ; ++$i) {
+            if ($i < $len && preg_match('`[A-Z]`', $s[$i - 1]) && preg_match('`[a-z]`', $s[$i])) {
+                $this->table_name .= '_';
+            }
+            $this->table_name .= strtolower($s[$i - 1]);
+        }
+        */
+        $this->da=$da;
+    }
+
+    //! An accessor
+    /**
+    * For SELECT queries
+    * @param $sql the query string
+    * @return mixed either false if error or object DataAccessResult
+    */
+    function &retrieve($sql) {
+        $result =& $this->da->fetch($sql);
+        if ($error = $result->isError()) {
+            $trace = debug_backtrace();
+            $i = isset($trace[1]) ? 1 : 0;
+            trigger_error($error .' ==> '. $sql ." @@ ". $trace[$i]['file'] .' at line '. $trace[$i]['line']);
+            $result = false;
+        }
+        return $result;
+    }
+
+    //! An accessor
+    /**
+    * For INSERT, UPDATE and DELETE queries
+    * @param $sql the query string
+    * @return boolean true if success
+    */
+    function update($sql) {
+        $result = $this->da->fetch($sql);
+        if ($error = $result->isError()) {
+            $trace = debug_backtrace();
+            $i = isset($trace[1]) ? 1 : 0;
+            trigger_error($error .' ==> '. $sql ." @@ ". $trace[$i]['file'] .' at line '. $trace[$i]['line']);
+            return false;
+        } else {
+            return true;
+        }
+    }
+    
+    /**
+    * Prepare ranking of items.
+    * 
+    * @see  https://partners.xrce.xerox.com/plugins/docman/?group_id=120&action=show&id=95
+    * 
+    * @param   int $id  The id of the item to rank. 0 if the item doesn't exist.
+    * @param   int $parent_id   The id of the element used to group items
+    * @param   mixed $rank    The rank asked for the items. Possible values are :
+    *                       '--'        => do not change the rank
+    *                       'beginning' => to put item before each others
+    *                       'end'       => to put item after each others
+    *                       'up'        => to put item before previous sibling
+    *                       'down'      => to put item after next sibling
+    *                       <int>       => to put item at a specific position. 
+    *                   Please note that for a new item ($id = 0) you must not use
+    *                   '--', 'up' or 'down' value
+    * @param   string $primary_key the column name of the primary key. Default 'id'
+    * @param   string $parent_key the column key used to groups items. Default 'parent_id'
+    * @param   string $rank_key the column key used to rank items. Default 'rank'
+    * @return  mixed false if there is no rank to update of the numerical
+    *          value of the new rank of the item. If return 'null' it means
+    *          that sth wrong happended.
+    */
+    function prepareRanking($id, $parent_id, $rank, $primary_key = 'id', $parent_key = 'parent_id', $rank_key = 'rank') {
+        $newRank = null;
+        
+        // First, check if there is already some items
+        $sql = sprintf('SELECT NULL'.
+                       ' FROM '. $this->table_name .
+                       ' WHERE '. $parent_key .' = %d',
+                       $parent_id);
+        $dar = $this->retrieve($sql);
+        if($dar && !$dar->isError() && $dar->rowCount() == 0) {
+            // No items: nice, just set the first one to 0.
+            $newRank = 0;
+        }
+        else {
+            switch((string)$rank) {
+            case '--':
+                $sql = sprintf('SELECT '. $rank_key .
+                               ' FROM '. $this->table_name .
+                               ' WHERE '. $primary_key .' = %d',
+                               (int)$id);
+                $dar = $this->retrieve($sql);
+                if($dar && !$dar->isError() && $dar->rowCount() == 1) {
+                    $row = $dar->current();
+                    $newRank = $row[$rank_key];
+                }
+                break;
+            case 'end':
+                // Simple case: just pickup the most high rank in the table
+                // and add 1 to be laster than the first.
+                $sql = sprintf('SELECT MAX('. $rank_key .')+1 as '. $rank_key .
+                               ' FROM '. $this->table_name .
+                               ' WHERE '. $parent_key .' = %d',
+                               $parent_id);
+                $dar = $this->retrieve($sql);
+                if($dar && !$dar->isError() && $dar->rowCount() == 1) {
+                    $row = $dar->current();
+                    $newRank = $row[$rank_key];
+                }
+                break;
+
+            case 'up':
+            case 'down':
+                // Those 2 cases are quite complex and are only mandatory if
+                // you want to 'Move up' or 'Move down' an item. If you can
+                // only select in a select box you can remove this part of
+                // the code.
+
+                // The general idea here is: we want to move up (or down) an
+                // item but we only know it's id and the sens (up/down) of the
+                // slide. Our goal is to exchange the rank value of the item
+                // behind (in case of up) with the current one.
+
+                // This is done in 2 steps:
+                // * first fetch the item_id and the rank of the item we want
+                //   to stole the place.
+                // * then exchange the 2 rank values.
+
+                if ($rank == 'down') {
+                    $op    = '>';
+                    $order = 'ASC';
+                } else {
+                    $op    = '<';
+                    $order = 'DESC';
+                }
+
+                // This SQL query aims to get the item_id and the rank of the item
+                // Just behind us (for 'up' case).
+                // In your implementation, USING(parent_id) should refer to the field
+                // that group all the items in one list.
+                $sql = sprintf('SELECT i1.'. $primary_key .' as id, i1.'. $rank_key .' as '. $rank_key .
+                                   ' FROM '. $this->table_name .' i1'.
+                                   '  INNER JOIN '. $this->table_name .' i2 USING('. $parent_key .')'.
+                                   ' WHERE i2.'. $primary_key .' = %d'.
+                                   '   AND i1.'. $parent_key .' = %d'.
+                                   '   AND i1.'. $rank_key .' %s i2.'. $rank_key .
+                                   ' ORDER BY i1.'. $rank_key .' %s'.
+                                   ' LIMIT 1',
+                                   $id,
+                                   $parent_id,
+                                   $op,
+                                   $order);
+                $dar = $this->retrieve($sql);
+                if ($dar && !$dar->isError() && $dar->rowCount() == 1) {
+                    $row = $dar->current();
+                    // This query exchange the two values.
+                    // Warning: the order is very important, please check that
+                    // your final query work as expected.
+                    $sql = sprintf('UPDATE '. $this->table_name .' i1, '. $this->table_name .' i2'.
+                                   ' SET i1.'. $rank_key .' = i2.'. $rank_key .', i2.'. $rank_key .' = %d'.
+                                   ' WHERE i1.'. $primary_key .' = %d '.
+                                   '  AND i2.'. $primary_key .' = %d',
+                                   $row[$rank_key],
+                                   $row['id'],
+                                   $id);
+                    $this->update($sql);
+                    $newRank = false;
+                }
+                break;
+
+            case 'beginning':
+                // This first part is quite simple: just pickup the lower rank
+                // in the table
+                $sql = sprintf('SELECT MIN('. $rank_key .') as '. $rank_key .
+                               ' FROM '. $this->table_name .
+                               ' WHERE '. $parent_key .' = %d',
+                               $parent_id);
+                $dar = $this->retrieve($sql);
+                if($dar && !$dar->isError()) {
+                    $row = $dar->current();
+                    $rank = $row[$rank_key];
+                }
+                // Very important: no break here, because we have to update all
+                // ranks upper:
+                // no break;
+
+            default:
+                // Here $rank is a numerical value that represent the rank after
+                // one item (user selected 'After XXX' in select box).
+                // The idea is to move up all the ranks upper to this value and to
+                // return the current value as the new rank.
+                $sql = sprintf('UPDATE '. $this->table_name .
+                               ' SET '. $rank_key .' = '. $rank_key .' + 1'.
+                               ' WHERE '. $parent_key .' = %d'.
+                               '  AND '. $rank_key .' >= %d',
+                               $parent_id, $rank);
+                $updated = $this->update($sql);
+                if($updated) {
+                    $newRank = $rank;
+                }
+            }
+        }
+        return $newRank;
+    }
+
+    /**
+     * Return the result of 'FOUND_ROWS()' SQL method for the last query.
+     */
+    function foundRows() {
+        $sql = "SELECT FOUND_ROWS() as nb";
+        $dar = $this->retrieve($sql);
+        if($dar && !$dar->isError()) {
+            $row = $dar->getRow();
+            return $row['nb'];
+        } else {
+            return false;
+        }
+    }
+}
+?>

Added: trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccess
===================================================================
--- trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccess	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccess	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,26 @@
+76c76
+<     function &fetch($sql,$params=array()) {
+---
+>     function &fetch($sql) {
+78c78
+<         $res = $this->mysql_query_params($sql,$params,$this->db);
+---
+>         $res = mysql_query($sql,$this->db);
+177,193d176
+<    # Parameterised query implementation for MySQL (similar PostgreSQL's PHP function pg_query_params)
+<    # Example: mysql_query_params( "SELECT * FROM my_table WHERE col1=$1 AND col2=$2", array( 42, "It's ok" ) );
+<     function mysql_query_params($sql,$params=array(),$database) {
+< 	if(!empty($params)) {
+< 		for ($i=1;$i<=count($params);$i++ ) {
+< 	   		$args[]="$".$i;	
+< 		}
+< 		return mysql_query(str_replace($args,$params,$sql),$database);
+< 	} else {
+< 		return mysql_query($sql,$database);
+< 	}
+< 	
+<     }
+< 
+< 
+< 
+< 

Added: trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccessObject
===================================================================
--- trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccessObject	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/common/dao/include/diffDataAccessObject	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,12 @@
+41,42c41,42
+<     function &retrieve($sql,$params=array()) {
+<         $result =& $this->da->fetch($sql,$params);
+---
+>     function &retrieve($sql) {
+>         $result =& $this->da->fetch($sql);
+58,59c58,59
+<     function update($sql,$params=array()) {
+<         $result = $this->da->fetch($sql,$params);
+---
+>     function update($sql) {
+>         $result = $this->da->fetch($sql);

Added: trunk/plugins/coclico/codendi-specific/plugins_utils.php~
===================================================================
--- trunk/plugins/coclico/codendi-specific/plugins_utils.php~	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/plugins_utils.php~	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,91 @@
+<?php
+
+require_once('pre.php');
+
+/**
+ * userIsAdmin - use this function to know if the user can administrate mailing lists
+ *
+ * This is a static method. Currently the user must be a project or a sitewide admin to administrate the mailing lists
+ *
+ * @return boolean true if the user can administrate mailing lists
+ */
+function userIsProjectAdmin($group_id) {
+	$current_user=UserManager::instance()->getCurrentUser();
+	if (!$current_user->isMember($group_id,'A')) {
+		return false;
+	} else {
+		return true;
+	}
+}
+
+function & getGroup($group_id)
+{
+
+	$pm = ProjectManager::instance();
+	$Group = $pm->getProject($group_id);
+	return $Group;
+}
+
+function isLogged(){
+	return user_isloggedin();
+}
+
+function ismember($group_id){
+	$current_user=UserManager::instance()->getCurrentUser();
+	return $current_user->isMember($group_id);
+}
+
+function getCurrentID()
+{
+	$current_user=UserManager::instance()->getCurrentUser();
+	return $current_user->getID();
+}
+function getEmail($id=false)
+{
+	if(!$id) {
+		$id =getCurrentID();
+	}
+	$user=UserManager::instance()->getUserByID($id);
+	return $user->getEmail();
+}
+function getPasswd()
+{
+	$current_user=UserManager::instance()->getCurrentUser();
+	return $current_user->getUserPw();
+}
+function getRealName()
+{
+	$current_user=UserManager::instance()->getCurrentUser();
+	return $current_user->getRealName();
+}
+function getRequest($param)
+{
+	$request =& HTTPRequest::instance();
+	if ($request->exist($param)) {
+		$result=$request->get($param);
+	}
+	else {
+		$result = false;
+	}
+	return $result;
+
+}
+function htmlRedirect($url) {
+	$GLOBALS['HTML']->redirect($url);
+}
+function htmlIframe($url,$poub) {
+	$GLOBALS['HTML']->iframe($url,array('class' => 'iframe_service'));
+}
+
+
+function helpButton($params)
+{
+	echo ' | ';
+	echo help_button($params,false,_('Help'));
+}
+function getIcon() {
+	echo '<IMG SRC="'.util_get_image_theme("ic/cfolder15.png").'" HEIGHT="13" WIDTH="15" BORDER="0">';
+}
+?>
+
+

Added: trunk/plugins/coclico/codendi-specific/www/include/plugins_utils.php
===================================================================
--- trunk/plugins/coclico/codendi-specific/www/include/plugins_utils.php	                        (rev 0)
+++ trunk/plugins/coclico/codendi-specific/www/include/plugins_utils.php	2010-05-10 12:01:16 UTC (rev 9702)
@@ -0,0 +1,42 @@
+<?php
+
+require_once('pre.php');
+$GLOBALS['mailman_lib_dir'] = '/var/lib/mailman';
+$GLOBALS['mailman_bin_dir'] = '/usr/lib/mailman/bin';
+$GLOBALS['forumml_arch'] = '/var/lib/mailman/archives';
+$GLOBALS['forumml_tmp'] = '/var/run/forumml';
+$GLOBALS['forumml_dir'] = '/var/lib/codendi/forumml';
+
+function isLogged(){
+        return user_isloggedin();
+}
+
+
+function htmlRedirect($url) {
+        $GLOBALS['HTML']->redirect($url);
+}
+function htmlIframe($url,$poub) {
+        $GLOBALS['HTML']->iframe($url,array('class' => 'iframe_service'));
+}
+
+
+function helpButton($params)
+{
+        echo ' | ';
+        echo help_button($params,false,_('Help'));
+}
+function getIcon() {
+        echo '<IMG SRC="'.util_get_image_theme("ic/cfolder15.png").'" HEIGHT="13" WIDTH="15" BORDER="0">';
+}
+function util_make_url ($loc) {
+        return session_make_url($loc);
+}
+function plugin_hook($hook,$params) {
+        $em =& EventManager::instance();
+        $em->processEvent($hook,$params);
+}
+function getImage($url) {
+return util_get_image_theme($url);
+}
+?>
+




More information about the Fusionforge-commits mailing list