2001-07-12 01:17:32 +02:00
< ? php
2006-10-04 19:40:33 +02:00
/**
* InfoLog - Storage object
*
* @ link http :// www . egroupware . org
* @ author Ralf Becker < RalfBecker - AT - outdoor - training . de >
* @ package infolog
* @ copyright ( c ) 2003 - 6 by Ralf Becker < RalfBecker - AT - outdoor - training . de >
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
* @ version $Id $
*/
include_once ( EGW_API_INC . '/class.solink.inc.php' );
/**
* storage object / db - layer for InfoLog
*
* all values passed to this class are run either through intval or addslashes to prevent query - insertion
* and for pgSql 7.3 compatibility
*
* @ package infolog
* @ author Ralf Becker < RalfBecker @ outdoor - training . de >
* @ copyright ( c ) by Ralf Becker < RalfBecker @ outdoor - training . de >
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
*/
class soinfolog // DB-Layer
{
2006-10-23 13:50:30 +02:00
/**
* Instance of the db class
*
* @ var egw_db
*/
2006-10-04 19:40:33 +02:00
var $db ;
2006-10-23 13:50:30 +02:00
/**
* Instance of the solink class
*
* @ var solink
*/
var $links ;
/**
* Grants from other users
*
* @ var array
*/
2006-10-04 19:40:33 +02:00
var $grants ;
2006-10-23 13:50:30 +02:00
/**
* Internal data array
*
* @ var array
*/
2006-10-04 19:40:33 +02:00
var $data = array ( );
2006-10-23 13:50:30 +02:00
/**
* Current user ( account_id )
*
* @ var int
*/
2006-10-04 19:40:33 +02:00
var $user ;
2006-10-23 13:50:30 +02:00
/**
* Infolog table - name
*
* @ var string
*/
2006-10-04 19:40:33 +02:00
var $info_table = 'egw_infolog' ;
2006-10-23 13:50:30 +02:00
/**
* Infolog custom fileds table - name
*
* @ var string
*/
2006-10-04 19:40:33 +02:00
var $extra_table = 'egw_infolog_extra' ;
2006-10-23 13:50:30 +02:00
/**
* Offset between server - and user - time in h
*
* @ var int
*/
var $tz_offset ;
2007-11-23 13:51:59 +01:00
/**
* @ var string
*/
var $extra_id = 'info_id' ;
/**
* @ var string
*/
var $extra_key = 'info_extra_name' ;
/**
* @ var string
*/
var $extra_value = 'info_extra_value' ;
/**
* custom fields backend
*
* @ var so_sql
*/
var $soextra ;
/**
* customfields name => array ( ... ) pairs
*
* @ var array
*/
var $customfields = array ();
/**
* content - types as name => array ( ... ) pairs
*
* @ var array
*/
var $content_types = array ();
2007-03-12 12:27:33 +01:00
2005-04-06 13:05:57 +02:00
/**
2007-03-12 12:27:33 +01:00
* Constructor
*
* @ param array $grants
* @ return soinfolog
2005-04-06 13:05:57 +02:00
*/
2007-03-12 12:27:33 +01:00
function soinfolog ( & $grants )
2001-07-12 01:17:32 +02:00
{
2006-10-04 19:40:33 +02:00
$this -> db = clone ( $GLOBALS [ 'egw' ] -> db );
$this -> db -> set_app ( 'infolog' );
2007-03-12 12:27:33 +01:00
$this -> grants =& $grants ;
2006-10-04 19:40:33 +02:00
$this -> user = $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ];
2003-06-14 15:51:53 +02:00
2006-10-04 19:40:33 +02:00
$this -> links =& new solink ();
2001-10-03 20:56:42 +02:00
2006-10-04 19:40:33 +02:00
$this -> tz_offset = $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ][ 'tz_offset' ];
2007-11-23 13:51:59 +01:00
$this -> soextra =& CreateObject ( 'etemplate.so_sql' );
$this -> soextra -> so_sql ( 'infolog' , $this -> extra_table );
$custom =& CreateObject ( 'admin.customfields' , 'infolog' );
$this -> customfields = $custom -> get_customfields ();
$this -> content_types = $custom -> get_content_types ();
if ( ! $this -> content_types )
{
$this -> content_types = $custom -> content_types = array ( 'n' => array (
'name' => 'infolog' ,
'options' => array (
'template' => 'infolog.edit' ,
'icon' => 'navbar.png'
)));
$custom -> save_repository ();
}
}
2003-09-08 02:40:42 +02:00
2006-10-24 12:08:21 +02:00
/**
* Check if use is responsible for an entry : he or one of his memberships is in responsible
*
* @ param array $info infolog entry as array
* @ return boolean
*/
function is_responsible ( $info )
{
static $user_and_memberships ;
if ( is_null ( $user_and_memberships ))
{
$user_and_memberships = $GLOBALS [ 'egw' ] -> accounts -> memberships ( $this -> user , true );
$user_and_memberships [] = $this -> user ;
}
return $info [ 'info_responsible' ] && array_intersect ( $info [ 'info_responsible' ], $user_and_memberships );
}
2006-10-04 19:40:33 +02:00
/**
* checks if user has the $required_rights to access $info_id ( private access is handled too )
*
* @ param array / int $info data or info_id of InfoLog entry
* @ param int $required_rights EGW_ACL_xyz anded together
* @ param boolean $implicit_edit = false responsible has only implicit read and add rigths , unless this is set to true
* @ return boolean True if access is granted else False
*/
function check_access ( $info , $required_rights , $implicit_edit = false )
{
if ( is_array ( $info ))
{
}
elseif (( int ) $info != $this -> data [ 'info_id' ]) // already loaded?
{
// dont change our own internal data,
// dont use new as it changes $phpgw->db
$private_info = $this ;
$info = $private_info -> read ( $info );
}
else
{
$info = $this -> data ;
}
if ( ! $info )
{
return False ;
2001-07-12 01:17:32 +02:00
}
2006-10-04 19:40:33 +02:00
$owner = $info [ 'info_owner' ];
2006-10-24 12:08:21 +02:00
2006-10-04 19:40:33 +02:00
$access_ok = $owner == $this -> user || // user has all rights
// ACL only on public entrys || $owner granted _PRIVATE
( !! ( $this -> grants [ $owner ] & $required_rights ) ||
2006-10-24 12:08:21 +02:00
$this -> is_responsible ( $info ) && // implicite rights for responsible user(s) and his memberships
( $required_rights == EGW_ACL_READ || $required_rights == EGW_ACL_ADD || $implicit_edit && $required_rights == EGW_ACL_EDIT )) &&
( $info [ 'info_access' ] == 'public' || !! ( $this -> grants [ $owner ] & EGW_ACL_PRIVATE ));
2006-10-04 19:40:33 +02:00
2006-10-24 12:08:21 +02:00
//echo "<p align=right>check_access(info_id=$info_id,requited=$required_rights,implicit_edit=$implicit_edit) owner=$owner, responsible=(".implode(',',$info['info_responsible'])."): access".($access_ok?"Ok":"Denied")."</p>\n";
2006-10-04 19:40:33 +02:00
return $access_ok ;
}
2006-10-24 12:08:21 +02:00
/**
* Filter for a given responsible user : info_responsible either contains a the user or one of his memberships
*
* @ param int $user
* @ return string
*
* @ todo make the responsible a second table and that filter a join with the responsible table
*/
function responsible_filter ( $user )
{
if ( ! $user ) return '0' ;
$responsible = $user > 0 ? $GLOBALS [ 'egw' ] -> accounts -> memberships ( $user , true ) :
$GLOBALS [ 'egw' ] -> accounts -> members ( $user , true );
$responsible [] = $user ;
foreach ( $responsible as $key => $uid )
{
$responsible [ $key ] = $this -> db -> concat ( " ',' " , 'info_responsible' , " ',' " ) . " LIKE '%, $uid ,%' " ;
}
//echo "<p align=right>responsible_filter($user) = ".'('.implode(' OR ',$responsible).')'."</p>\n";
return '(' . implode ( ' OR ' , $responsible ) . ')' ;
}
2006-10-04 19:40:33 +02:00
/**
* generate sql to be AND ' ed into a query to ensure ACL is respected ( incl . _PRIVATE )
*
2007-06-21 20:49:57 +02:00
* @ param string $filter : none | all - list all entrys user have rights to see < br >
* private | own - list only his personal entrys ( incl . those he is responsible for !!! ),
* responsible | my = entries the user is responsible for
* delegated = entries the user delegated to someone else
2006-10-04 19:40:33 +02:00
* @ return string the necesary sql
*/
function aclFilter ( $filter = False )
{
2007-10-29 20:46:46 +01:00
preg_match ( '/(my|responsible|delegated|own|privat|private|all|none|user)([0-9]*)/' , $filter_was = $filter , $vars );
2006-10-04 19:40:33 +02:00
$filter = $vars [ 1 ];
$f_user = intval ( $vars [ 2 ]);
2001-07-12 01:17:32 +02:00
2006-10-04 19:40:33 +02:00
if ( isset ( $this -> acl_filter [ $filter . $f_user ]))
2001-07-14 23:44:01 +02:00
{
2006-10-04 19:40:33 +02:00
return $this -> acl_filter [ $filter . $f_user ]; // used cached filter if found
}
2006-10-24 12:08:21 +02:00
2007-06-21 20:49:57 +02:00
$filtermethod = " (info_owner= $this->user " ; // user has all rights
if ( $filter == 'my' || $filter == 'responsible' )
{
$filtermethod .= " AND info_responsible='0' " ;
}
if ( $filter == 'delegated' )
2006-10-04 19:40:33 +02:00
{
2007-06-21 20:49:57 +02:00
$filtermethod .= " AND info_responsible<>'0') " ;
}
else
{
if ( is_array ( $this -> grants ))
2001-07-14 23:44:01 +02:00
{
2007-06-21 20:49:57 +02:00
foreach ( $this -> grants as $user => $grant )
2001-07-14 23:44:01 +02:00
{
2007-06-21 20:49:57 +02:00
// echo "<p>grants: user=$user, grant=$grant</p>";
if ( $grant & ( EGW_ACL_READ | EGW_ACL_EDIT ))
{
$public_user_list [] = $user ;
}
if ( $grant & EGW_ACL_PRIVATE )
{
$private_user_list [] = $user ;
}
2001-07-12 01:17:32 +02:00
}
2007-06-21 20:49:57 +02:00
if ( count ( $private_user_list ))
2003-09-07 18:55:36 +02:00
{
2007-06-21 20:49:57 +02:00
$has_private_access = 'info_owner IN (' . implode ( ',' , $private_user_list ) . ')' ;
2003-09-07 18:55:36 +02:00
}
2001-07-12 01:17:32 +02:00
}
2007-06-21 20:49:57 +02:00
// implicit read-rights for responsible user
$filtermethod .= " OR ( " . $this -> responsible_filter ( $this -> user ) . " AND info_access='public') " ;
// private: own entries plus the one user is responsible for
2007-10-29 20:46:46 +01:00
if ( $filter == 'private' || $filter == 'privat' || $filter == 'own' )
2005-07-14 09:35:11 +02:00
{
2007-06-21 20:49:57 +02:00
$filtermethod .= " OR ( " . $this -> responsible_filter ( $this -> user ) .
( $filter == 'own' && count ( $public_user_list ) ? // offer's should show up in own, eg. startpage, but need read-access
" OR info_status = 'offer' AND info_owner IN( " . implode ( ',' , $public_user_list ) . ')' : '' ) . " ) " .
" AND (info_access='public' " . ( $has_private_access ? " OR $has_private_access " : '' ) . ')' ;
2005-07-14 09:35:11 +02:00
}
2007-06-21 20:49:57 +02:00
elseif ( $filter != 'my' && $filter != 'responsible' ) // none --> all entrys user has rights to see
2001-07-14 23:44:01 +02:00
{
2007-06-21 20:49:57 +02:00
if ( $has_private_access )
{
$filtermethod .= " OR $has_private_access " ;
}
if ( count ( $public_user_list ))
{
$filtermethod .= " OR (info_access='public' AND info_owner IN( " . implode ( ',' , $public_user_list ) . '))' ;
}
2001-07-14 23:44:01 +02:00
}
2007-06-21 20:49:57 +02:00
$filtermethod .= ') ' ;
if ( $filter == 'user' && $f_user > 0 )
2001-07-14 23:44:01 +02:00
{
2007-07-03 06:37:56 +02:00
$filtermethod .= " AND (info_owner= $f_user AND info_responsible='0' OR " . $this -> responsible_filter ( $f_user ) . ')' ;
2006-10-04 19:40:33 +02:00
}
}
//echo "<p>aclFilter(filter='$filter_was',user='$user') = '$filtermethod', privat_user_list=".print_r($privat_user_list,True).", public_user_list=".print_r($public_user_list,True)."</p>\n";
return $this -> acl_filter [ $filter . $f_user ] = $filtermethod ; // cache the filter
}
/**
* generate sql to filter based on the status of the log - entry
*
2007-06-21 20:49:57 +02:00
* @ param string $filter done = done or billed , open = not ( done , billed , cancelled or deleted ), offer = offer
* @ param boolean $prefix_and = true if true prefix the fileter with ' AND '
2006-10-04 19:40:33 +02:00
* @ return string the necesary sql
*/
2007-06-21 20:49:57 +02:00
function statusFilter ( $filter = '' , $prefix_and = true )
2006-10-04 19:40:33 +02:00
{
2007-06-21 20:49:57 +02:00
preg_match ( '/(done|open|offer|deleted)/' , $filter , $vars );
2006-10-04 19:40:33 +02:00
$filter = $vars [ 1 ];
switch ( $filter )
{
2007-06-21 20:49:57 +02:00
case 'done' : $filter = " info_status IN ('done','billed','cancelled') " ; break ;
case 'open' : $filter = " NOT (info_status IN ('done','billed','cancelled','deleted')) " ; break ;
case 'offer' : $filter = " info_status = 'offer' " ; break ;
case 'deleted' : $filter = " info_status = 'deleted' " ; break ;
default : $filter = " info_status <> 'deleted' " ; break ;
2006-10-04 19:40:33 +02:00
}
2007-06-21 20:49:57 +02:00
return ( $prefix_and ? ' AND ' : '' ) . $filter ;
2006-10-04 19:40:33 +02:00
}
/**
* generate sql to filter based on the start - and enddate of the log - entry
*
2007-06-21 20:49:57 +02:00
* @ param string $filter upcoming = startdate is in the future
* today : startdate < tomorrow
* overdue : enddate < tomorrow
* date : today <= startdate && startdate < tomorrow
* enddate : today <= enddate && enddate < tomorrow
2006-10-04 19:40:33 +02:00
* limitYYYY / MM / DD not older or open
* @ return string the necesary sql
*/
function dateFilter ( $filter = '' )
{
2007-06-21 20:49:57 +02:00
preg_match ( '/(upcoming|today|overdue|date|enddate)([-\\/.0-9]*)/' , $filter , $vars );
2006-10-04 19:40:33 +02:00
$filter = $vars [ 1 ];
if ( isset ( $vars [ 2 ]) && ! empty ( $vars [ 2 ]) && ( $date = split ( '[-/.]' , $vars [ 2 ])))
{
$today = mktime ( - $this -> tz_offset , 0 , 0 , intval ( $date [ 1 ]), intval ( $date [ 2 ]), intval ( $date [ 0 ]));
$tomorrow = mktime ( - $this -> tz_offset , 0 , 0 , intval ( $date [ 1 ]), intval ( $date [ 2 ]) + 1 , intval ( $date [ 0 ]));
}
else
{
$now = getdate ( time () - 60 * 60 * $this -> tz_offset );
$tomorrow = mktime ( - $this -> tz_offset , 0 , 0 , $now [ 'mon' ], $now [ 'mday' ] + 1 , $now [ 'year' ]);
}
switch ( $filter )
{
case 'upcoming' :
return " AND info_startdate >= ' $tomorrow ' " ;
case 'today' :
return " AND info_startdate < ' $tomorrow ' " ;
case 'overdue' :
return " AND (info_enddate != 0 AND info_enddate < ' $tomorrow ') " ;
case 'date' :
if ( ! $today || ! $tomorrow )
2003-09-07 18:55:36 +02:00
{
2006-10-04 19:40:33 +02:00
return '' ;
2001-07-12 01:17:32 +02:00
}
2006-10-04 19:40:33 +02:00
return " AND ( $today <= info_startdate AND info_startdate < $tomorrow ) " ;
2007-06-21 20:49:57 +02:00
case 'enddate' :
if ( ! $today || ! $tomorrow )
{
return '' ;
}
return " AND ( $today <= info_enddate AND info_enddate < $tomorrow ) " ;
2006-10-04 19:40:33 +02:00
case 'limit' :
return " AND (info_modified >= ' $today ' OR NOT (info_status IN ('done','billed','cancelled'))) " ;
}
return '' ;
}
2003-09-07 18:55:36 +02:00
2006-10-04 19:40:33 +02:00
/**
* initialise the internal $this -> data to be empty
*
* only non - empty values got initialised
*/
function init ()
{
$this -> data = array (
'info_owner' => $this -> user ,
'info_priority' => 1 ,
'info_responsible' => array (),
);
}
2005-10-05 09:50:47 +02:00
2006-10-04 19:40:33 +02:00
/**
* read InfoLog entry $info_id
*
* some cacheing is done to prevent multiple reads of the same entry
*
* @ param $info_id id of log - entry
* @ return array / boolean the entry as array or False on error ( eg . entry not found )
*/
function read ( $info_id ) // did _not_ ensure ACL
{
$info_id = ( int ) $info_id ;
if ( $info_id && $info_id == $this -> data [ 'info_id' ])
{
return $this -> data ; // return the already read entry
}
if ( $info_id <= 0 || ! $this -> db -> select ( $this -> info_table , '*' , array ( 'info_id' => $info_id ), __LINE__ , __FILE__ ) ||
! (( $this -> data = $this -> db -> row ( true ))))
{
$this -> init ( );
return False ;
}
if ( ! is_array ( $this -> data [ 'info_responsible' ]))
{
$this -> data [ 'info_responsible' ] = $this -> data [ 'info_responsible' ] ? explode ( ',' , $this -> data [ 'info_responsible' ]) : array ();
2003-09-07 18:55:36 +02:00
}
2006-10-04 19:40:33 +02:00
$this -> db -> select ( $this -> extra_table , 'info_extra_name,info_extra_value' , array ( 'info_id' => $info_id ), __LINE__ , __FILE__ );
while ( $this -> db -> next_record ())
{
$this -> data [ '#' . $this -> db -> f ( 0 )] = $this -> db -> f ( 1 );
}
return $this -> data ;
}
2001-07-12 01:17:32 +02:00
2006-10-04 19:40:33 +02:00
/**
* Read the status of the given infolog - ids
*
* @ param array $ids array with id ' s
* @ return array with id => status pairs
*/
function get_status ( $ids )
{
$this -> db -> select ( $this -> info_table , 'info_id,info_type,info_status,info_percent' , array ( 'info_id' => $ids ), __LINE__ , __FILE__ );
while (( $info = $this -> db -> row ( true )))
{
switch ( $info [ 'info_type' ] . '-' . $info [ 'info_status' ])
{
case 'phone-not-started' :
$status = 'call' ;
break ;
case 'phone-ongoing' :
$status = 'will-call' ;
break ;
default :
$status = $info [ 'info_status' ] == 'ongoing' ? $info [ 'info_percent' ] . '%' : $info [ 'info_status' ];
}
$stati [ $info [ 'info_id' ]] = $status ;
2001-07-15 23:42:17 +02:00
}
2006-10-04 19:40:33 +02:00
return $stati ;
}
2001-07-15 23:42:17 +02:00
2006-10-04 19:40:33 +02:00
/**
* delete InfoLog entry $info_id AND the links to it
*
* @ param int $info_id id of log - entry
* @ param bool $delete_children delete the children , if not set there parent - id to $new_parent
* @ param int $new_parent new parent - id to set for subs
*/
function delete ( $info_id , $delete_children = True , $new_parent = 0 ) // did _not_ ensure ACL
{
//echo "<p>soinfolog::delete($info_id,'$delete_children',$new_parent)</p>\n";
if (( int ) $info_id <= 0 )
2001-07-15 23:42:17 +02:00
{
2006-10-04 19:40:33 +02:00
return ;
}
$this -> db -> delete ( $this -> info_table , array ( 'info_id' => $info_id ), __LINE__ , __FILE__ );
$this -> db -> delete ( $this -> extra_table , array ( 'info_id' => $info_id ), __LINE__ , __FILE__ );
$this -> links -> unlink ( 0 , 'infolog' , $info_id );
2001-07-15 23:42:17 +02:00
2006-10-04 19:40:33 +02:00
if ( $this -> data [ 'info_id' ] == $info_id )
{
$this -> init ( );
2001-07-12 01:17:32 +02:00
}
2006-10-04 19:40:33 +02:00
// delete children, if they are owned by the user
if ( $delete_children )
{
$db2 = clone ( $this -> db ); // we need an extra result-set
$db2 -> select ( $this -> info_table , 'info_id' , array (
'info_id_parent' => $info_id ,
'info_owner' => $this -> user ,
), __LINE__ , __FILE__ );
while ( $db2 -> next_record ())
2003-06-14 15:51:53 +02:00
{
2006-10-04 19:40:33 +02:00
$this -> delete ( $db2 -> f ( 0 ), $delete_children );
2003-06-14 15:51:53 +02:00
}
2006-10-04 19:40:33 +02:00
}
// set parent_id to $new_parent or 0 for all not deleted children
$this -> db -> update ( $this -> info_table , array ( 'info_id_parent' => $new_parent ), array ( 'info_id_parent' => $info_id ), __LINE__ , __FILE__ );
}
2007-06-21 20:49:57 +02:00
/**
* Return array with children of $info_id as info_id => info_owner pairs
*
* @ param int $info_id
* @ return array with info_id => info_owner pairs
*/
function get_children ( $info_id )
{
$this -> db -> select ( $this -> info_table , 'info_id,info_owner' , array (
'info_id_parent' => $info_id ,
), __LINE__ , __FILE__ );
$children = array ();
while (( $row = $this -> db -> row ( true )))
{
$children [ $row [ 'info_id' ]] = $row [ 'info_owner' ];
}
return $children ;
}
2002-09-01 22:41:36 +02:00
2006-10-04 19:40:33 +02:00
/**
* changes or deletes entries with a spezified owner ( for hook_delete_account )
*
* @ param $owner old owner
* @ param $new_owner new owner or 0 if entries should be deleted
*/
function change_delete_owner ( $owner , $new_owner = 0 ) // new_owner=0 means delete
{
if ( ! ( int ) $new_owner )
{
$db2 = clone ( $this -> db ); // we need an extra result-set
$db2 -> select ( $this -> info_table , 'info_id' , array ( 'info_owner' => $owner ), __LINE__ , __FILE__ );
while ( $db2 -> next_record ())
2003-08-28 16:31:11 +02:00
{
2006-10-04 19:40:33 +02:00
$this -> delete ( $this -> db -> f ( 0 ), False );
2003-08-28 16:31:11 +02:00
}
2001-07-12 01:17:32 +02:00
}
2006-10-04 19:40:33 +02:00
else
{
$this -> db -> update ( $this -> info_table , array ( 'info_owner' => $new_owner ), array ( 'info_owner' => $owner ), __LINE__ , __FILE__ );
}
2007-06-21 20:49:57 +02:00
// ToDo: does not work with multiple owners!!!
2006-10-04 19:40:33 +02:00
$this -> db -> update ( $this -> info_table , array ( 'info_responsible' => $new_owner ), array ( 'info_responsible' => $owner ), __LINE__ , __FILE__ );
}
/**
* writes the given $values to InfoLog , a new entry gets created if info_id is not set or 0
*
* @ param array $values with the data of the log - entry
* @ param int $check_modified = 0 old modification date to check before update ( include in WHERE )
* @ return int / boolean info_id , false on error or 0 if the entry has been updated in the meantime
*/
function write ( $values , $check_modified = 0 ) // did _not_ ensure ACL
{
//echo "soinfolog::write(,$check_modified) values="; _debug_array($values);
$info_id = ( int ) $values [ 'info_id' ];
2001-07-12 01:17:32 +02:00
2006-10-04 19:40:33 +02:00
if ( array_key_exists ( 'info_responsible' , $values )) // isset($values['info_responsible']) returns false for NULL!
2002-11-20 20:58:15 +01:00
{
2006-10-04 19:40:33 +02:00
$values [ 'info_responsible' ] = $values [ 'info_responsible' ] ? implode ( ',' , $values [ 'info_responsible' ]) : '0' ;
}
$table_def = $this -> db -> get_table_definitions ( 'infolog' , $this -> info_table );
$to_write = array ();
foreach ( $values as $key => $val )
{
if ( $key != 'info_id' && isset ( $table_def [ 'fd' ][ $key ]))
2002-11-20 20:58:15 +01:00
{
2006-10-04 19:40:33 +02:00
$to_write [ $key ] = $this -> data [ $key ] = $val ; // update internal data
2002-11-20 20:58:15 +01:00
}
2006-10-04 19:40:33 +02:00
}
2006-12-08 08:10:27 +01:00
// writing no price as SQL NULL (required by postgres)
if ( $to_write [ 'info_price' ] === '' ) $to_write [ 'info_price' ] = NULL ;
2006-10-04 19:40:33 +02:00
if (( $this -> data [ 'info_id' ] = $info_id ))
{
$where = array ( 'info_id' => $info_id );
if ( $check_modified ) $where [ 'info_datemodified' ] = $check_modified ;
if ( ! $this -> db -> update ( $this -> info_table , $to_write , $where , __LINE__ , __FILE__ ))
2002-11-20 20:58:15 +01:00
{
2006-10-04 19:40:33 +02:00
return false ; // Error
2002-11-20 20:58:15 +01:00
}
2006-10-04 19:40:33 +02:00
if ( $this -> db -> affected_rows () < 1 ) return 0 ; // someone else updated the modtime or deleted the entry
2002-11-20 20:58:15 +01:00
}
2006-10-04 19:40:33 +02:00
else
2001-07-14 23:44:01 +02:00
{
2006-10-04 19:40:33 +02:00
if ( ! isset ( $to_write [ 'info_id_parent' ])) $to_write [ 'info_id_parent' ] = 0 ; // must not be null
2003-08-28 16:31:11 +02:00
2006-10-04 19:40:33 +02:00
$this -> db -> insert ( $this -> info_table , $to_write , false , __LINE__ , __FILE__ );
$info_id = $this -> data [ 'info_id' ] = $this -> db -> get_last_insert_id ( $this -> info_table , 'info_id' );
}
//echo "<p>soinfolog.write values= "; _debug_array($values);
// write customfields now
foreach ( $values as $key => $val )
{
if ( $key [ 0 ] != '#' )
2001-07-14 23:44:01 +02:00
{
2006-10-04 19:40:33 +02:00
continue ; // no customfield
2001-07-14 23:44:01 +02:00
}
2006-10-04 19:40:33 +02:00
$this -> data [ $key ] = $val ; // update internal data
2005-10-05 09:50:47 +02:00
2006-10-04 19:40:33 +02:00
$this -> db -> insert ( $this -> extra_table , array (
'info_extra_value' => $val
), array (
'info_id' => $info_id ,
'info_extra_name' => substr ( $key , 1 ),
), __LINE__ , __FILE__ );
}
// echo "<p>soinfolog.write this->data= "; _debug_array($this->data);
2003-08-28 16:31:11 +02:00
2006-10-04 19:40:33 +02:00
return $this -> data [ 'info_id' ];
}
2003-06-14 15:51:53 +02:00
2006-10-04 19:40:33 +02:00
/**
* count the sub - entries of $info_id
*
* This is done now be search too ( in key info_anz_subs ), if DB can use sub - queries
*
* @ param $info_id id of log - entry
* @ return int the number of sub - entries
*/
function anzSubs ( $info_id )
{
if (( $info_id = intval ( $info_id )) <= 0 )
{
return 0 ;
2001-07-12 01:17:32 +02:00
}
2006-10-04 19:40:33 +02:00
$this -> db -> select ( $this -> info_table , 'count(*)' , array (
'info_id_parent' => $info_id ,
$this -> aclFilter ()
), __LINE__ , __FILE__ );
$this -> db -> next_record ();
//echo "<p>anzSubs($info_id) = ".$this->db->f(0)." ($sql)</p>\n";
return $this -> db -> f ( 0 );
}
2007-06-21 20:49:57 +02:00
2006-10-04 19:40:33 +02:00
/**
* searches InfoLog for a certain pattern in $query
*
* If DB can use sub - queries , the number of subs are under the key info_anz_subs .
*
* @ param $query [ order ] column - name to sort after
* @ param $query [ sort ] sort - order DESC or ASC
* @ param $query [ filter ] string with combination of acl - , date - and status - filters , eg . 'own-open-today' or ''
* @ param $query [ cat_id ] category to use or 0 or unset
* @ param $query [ search ] pattern to search , search is done in info_from , info_subject and info_des
* @ param $query [ action ] / $query [ action_id ] if only entries linked to a specified app / entry show be used
* @ param & $query [ start ], & $query [ total ] nextmatch - parameters will be used and set if query returns less entries
* @ param $query [ col_filter ] array with column - name - data pairs , data == '' means no filter ( ! )
* @ param $query [ subs ] boolean return subs or not , if unset the user preference is used
* @ param $query [ num_rows ] number of rows to return if $query [ start ] is set , default is to use the value from the general prefs
* @ return array with id ' s as key of the matching log - entries
*/
function search ( & $query )
{
//echo "<p>soinfolog.search(".print_r($query,True).")</p>\n";
$action2app = array (
'addr' => 'addressbook' ,
'proj' => 'projects' ,
'event' => 'calendar'
);
$action = isset ( $action2app [ $query [ 'action' ]]) ? $action2app [ $query [ 'action' ]] : $query [ 'action' ];
2006-12-07 13:47:11 +01:00
$action_id = ( strpos ( $query [ 'action_id' ], ',' ) !== false ) ? explode ( ',' , $query [ 'action_id' ]) : $query [ 'action_id' ];
2006-10-04 19:40:33 +02:00
if ( $action != '' )
2001-07-14 23:44:01 +02:00
{
2006-10-23 13:50:30 +02:00
$links = $this -> links -> get_links ( $action == 'sp' ? 'infolog' : $action , $action_id , 'infolog' );
2001-07-14 23:44:01 +02:00
2006-10-04 19:40:33 +02:00
if ( count ( $links ))
2002-10-16 02:23:39 +02:00
{
2006-10-04 19:40:33 +02:00
$link_extra = ( $action == 'sp' ? 'OR' : 'AND' ) . " main.info_id IN ( " . implode ( ',' , $links ) . ')' ;
2002-09-01 22:41:36 +02:00
}
2006-10-04 19:40:33 +02:00
}
2007-12-13 12:18:44 +01:00
$sortbycf = '' ;
if ( ! empty ( $query [ 'order' ]) && ( eregi ( '^[a-z_0-9, ]+$' , $query [ 'order' ]) || stripos ( $query [ 'order' ], '#' ) !== FALSE ) && ( empty ( $query [ 'sort' ]) || eregi ( '^(DESC|ASC)$' , $query [ 'sort' ])))
2006-10-04 19:40:33 +02:00
{
$order = array ();
foreach ( explode ( ',' , $query [ 'order' ]) as $val )
2001-07-14 23:44:01 +02:00
{
2006-10-04 19:40:33 +02:00
$val = trim ( $val );
2007-12-13 12:18:44 +01:00
if ( substr ( $val , 0 , 1 ) == '#' ) {
$sortbycf = substr ( $val , 1 );
$val = " cfsortcrit " ;
} else {
$val = ( substr ( $val , 0 , 5 ) != 'info_' ? 'info_' : '' ) . $val ;
if ( $val == 'info_des' && $this -> db -> capabilities [ 'order_on_text' ] !== true )
{
if ( ! $this -> db -> capabilities [ 'order_on_text' ]) continue ;
2005-11-12 14:25:59 +01:00
2007-12-13 12:18:44 +01:00
$val = sprintf ( $this -> db -> capabilities [ 'order_on_text' ], $val );
}
2004-03-13 18:58:37 +01:00
}
2006-10-04 19:40:33 +02:00
$order [] = $val ;
2001-07-14 23:44:01 +02:00
}
2006-10-04 19:40:33 +02:00
$ordermethod = 'ORDER BY ' . implode ( ',' , $order ) . ' ' . $query [ 'sort' ];
}
else
{
$ordermethod = 'ORDER BY info_datemodified DESC' ; // newest first
}
$acl_filter = $filtermethod = $this -> aclFilter ( $query [ 'filter' ]);
$filtermethod .= $this -> statusFilter ( $query [ 'filter' ]);
$filtermethod .= $this -> dateFilter ( $query [ 'filter' ]);
2007-12-13 12:18:44 +01:00
$cfcolfilter = 0 ;
2006-10-04 19:40:33 +02:00
if ( is_array ( $query [ 'col_filter' ]))
{
foreach ( $query [ 'col_filter' ] as $col => $data )
2003-12-09 01:08:31 +01:00
{
2007-12-13 12:18:44 +01:00
if ( substr ( $col , 0 , 5 ) != 'info_' && substr ( $col , 0 , 1 ) != '#' ) $col = 'info_' . $col ;
2006-10-04 19:40:33 +02:00
if ( ! empty ( $data ) && eregi ( '^[a-z_0-9]+$' , $col ))
2003-12-09 01:08:31 +01:00
{
2006-10-04 19:40:33 +02:00
if ( $col == 'info_responsible' )
2003-12-09 01:08:31 +01:00
{
2006-10-04 19:40:33 +02:00
$data = ( int ) $data ;
if ( ! $data ) continue ;
2006-10-24 13:58:14 +02:00
$filtermethod .= " AND ( " . $this -> responsible_filter ( $data ) . " OR info_responsible='0' AND " .
$this -> db -> expression ( $this -> info_table , array (
'info_owner' => $data > 0 ? $data : $GLOBALS [ 'egw' ] -> accounts -> members ( $data , true )
)) . ')' ;
2003-12-09 01:08:31 +01:00
}
2006-10-04 19:40:33 +02:00
else
{
2006-10-24 13:58:14 +02:00
$filtermethod .= ' AND ' . $this -> db -> expression ( $this -> info_table , array ( $col => $data ));
2006-10-04 19:40:33 +02:00
}
2003-12-09 01:08:31 +01:00
}
2007-12-13 12:18:44 +01:00
if ( substr ( $col , 0 , 1 ) == '#' && $query [ 'custom_fields' ] && $data ) {
$filtermethod .= " and main.info_id in (select distinct info_id from $this->extra_table " . " where (info_extra_name=' " . substr ( $col , 1 ) . " ' and info_extra_value=' " . $data . " ')) " ;
$cfcolfilter ++ ;
}
2003-12-09 01:08:31 +01:00
}
2006-10-04 19:40:33 +02:00
}
//echo "<p>filtermethod='$filtermethod'</p>";
2001-07-14 23:44:01 +02:00
2006-10-04 19:40:33 +02:00
if (( int ) $query [ 'cat_id' ])
{
//$filtermethod .= ' AND info_cat='.intval($query['cat_id']).' ';
if ( ! is_object ( $GLOBALS [ 'egw' ] -> categories ))
2001-07-14 23:44:01 +02:00
{
2006-10-04 19:40:33 +02:00
$GLOBALS [ 'egw' ] -> categories =& CreateObject ( 'phpgwapi.categories' );
2001-07-14 23:44:01 +02:00
}
2006-10-04 19:40:33 +02:00
$cats = $GLOBALS [ 'egw' ] -> categories -> return_all_children (( int ) $query [ 'cat_id' ]);
$filtermethod .= ' AND info_cat' . ( count ( $cats ) > 1 ? ' IN (' . implode ( ',' , $cats ) . ') ' : '=' . ( int ) $query [ 'cat_id' ]);
}
$join = $distinct = $count_subs = '' ;
if ( $query [ 'query' ]) $query [ 'search' ] = $query [ 'query' ]; // allow both names
if ( $query [ 'search' ]) // we search in _from, _subject, _des and _extra_value for $query
{
$pattern = $this -> db -> quote ( '%' . $query [ 'search' ] . '%' );
2004-09-19 18:15:53 +02:00
2006-10-04 19:40:33 +02:00
$columns = array ( 'info_from' , 'info_addr' , 'info_location' , 'info_subject' , 'info_extra_value' );
// at the moment MaxDB 7.5 cant cast nor search text columns, it's suppost to change in 7.6
if ( $this -> db -> capabilities [ 'like_on_text' ]) $columns [] = 'info_des' ;
2005-11-12 14:25:59 +01:00
2006-10-04 19:40:33 +02:00
$sql_query = 'AND (' . ( is_numeric ( $query [ 'search' ]) ? 'main.info_id=' . ( int ) $query [ 'search' ] . ' OR ' : '' ) .
implode ( " LIKE $pattern OR " , $columns ) . " LIKE $pattern ) " ;
2007-11-23 13:51:59 +01:00
}
if ( $query [ 'search' ] || $query [ 'custom_fields' ] )
{
2007-12-13 12:18:44 +01:00
$join = ( $cfcolfilter > 0 ? '' : " LEFT " ) . " JOIN $this->extra_table ON main.info_id= $this->extra_table .info_id " ;
2006-10-04 19:40:33 +02:00
// mssql and others cant use DISTICT if text columns (info_des) are involved
$distinct = $this -> db -> capabilities [ 'distinct_on_text' ] ? 'DISTINCT' : '' ;
}
$pid = 'AND info_id_parent=' . ( $action == 'sp' ? $query [ 'action_id' ] : 0 );
2001-07-14 23:44:01 +02:00
2006-10-04 19:40:33 +02:00
if ( ! $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'infolog' ][ 'listNoSubs' ] &&
$action != 'sp' || isset ( $query [ 'subs' ]) && $query [ 'subs' ])
{
$pid = '' ;
}
$ids = array ( );
if ( $action == '' || $action == 'sp' || count ( $links ))
{
$sql_query = " FROM $this->info_table main $join WHERE ( $filtermethod $pid $sql_query ) $link_extra " ;
$this -> db -> query ( $sql = " SELECT $distinct main.info_id " . $sql_query , __LINE__ , __FILE__ );
$query [ 'total' ] = $this -> db -> num_rows ();
if ( isset ( $query [ 'start' ]) && $query [ 'start' ] > $query [ 'total' ])
2001-07-14 23:44:01 +02:00
{
2006-10-04 19:40:33 +02:00
$query [ 'start' ] = 0 ;
2001-07-14 23:44:01 +02:00
}
2006-10-04 19:40:33 +02:00
if ( $this -> db -> capabilities [ 'sub_queries' ])
2003-06-14 15:51:53 +02:00
{
2006-10-04 19:40:33 +02:00
$count_subs = " ,(SELECT count(*) FROM $this->info_table sub WHERE sub.info_id_parent=main.info_id AND $acl_filter ) AS info_anz_subs " ;
2001-07-14 23:44:01 +02:00
}
2007-11-23 13:51:59 +01:00
$info_customfield = " " ;
2007-12-13 12:18:44 +01:00
if ( $sortbycf != '' ) {
$info_customfield = " , (select distinct info_extra_value from $this->extra_table sub2 where sub2.info_id=main.info_id and info_extra_name=' " . $sortbycf . " ') AS cfsortcrit " ;
}
2007-11-23 13:51:59 +01:00
//echo "SELECT $distinct main.* $count_subs $info_customfield $sql_query $ordermethod"."<br>";
$this -> db -> query ( $sql = " SELECT $distinct main.* $count_subs $info_customfield $sql_query $ordermethod " , __LINE__ , __FILE__ ,
2006-10-04 19:40:33 +02:00
( int ) $query [ 'start' ], isset ( $query [ 'start' ]) ? ( int ) $query [ 'num_rows' ] : - 1 );
//echo "<p>db::query('$sql',,,".(int)$query['start'].','.(isset($query['start']) ? (int) $query['num_rows'] : -1).")</p>\n";
while (( $info =& $this -> db -> row ( true )))
{
$info [ 'info_responsible' ] = $info [ 'info_responsible' ] ? explode ( ',' , $info [ 'info_responsible' ]) : array ();
$ids [ $info [ 'info_id' ]] = $info ;
2001-07-14 23:44:01 +02:00
}
2006-10-21 15:07:32 +02:00
if ( $ids && $query [ 'custom_fields' ])
{
$this -> db -> select ( $this -> extra_table , '*' , array ( 'info_id' => array_keys ( $ids )), __LINE__ , __FILE__ );
while ( $row = $this -> db -> row ( true ))
{
2007-11-23 13:51:59 +01:00
if (( isset ( $row [ 'info_extra_value' ]) && strlen ( $row [ 'info_extra_value' ]) > 0 ) &&
( stripos ( $query [ 'selectcols' ], '#' . $row [ 'info_extra_name' ]) !== FALSE || ! isset ( $query [ 'selectcols' ]) ||
( stripos ( $query [ 'selectcols' ], '#' ) === FALSE && stripos ( $query [ 'selectcols' ], 'customfields' ) !== FALSE ) ))
{
$ids [ $row [ 'info_id' ]][ '#' . $row [ 'info_extra_name' ]] = $row [ 'info_extra_value' ];
2007-12-13 12:18:44 +01:00
} else {
unset ( $ids [ $row [ 'info_id' ]][ '#' . $row [ 'info_extra_name' ]]);
2007-11-23 13:51:59 +01:00
}
2006-10-21 15:07:32 +02:00
}
}
2001-07-14 23:44:01 +02:00
}
2006-10-04 19:40:33 +02:00
else
{
$query [ 'start' ] = $query [ 'total' ] = 0 ;
}
return $ids ;
2001-07-12 01:17:32 +02:00
}
2007-06-21 20:49:57 +02:00
/**
* Query infolog for users with open entries , either own or responsible , with start or end within 4 days
*
* This functions tries to minimize the users really checked with the complete filters , as creating a
* user enviroment and running the specific check costs ...
*
* @ return array with acount_id ' s groups get resolved to there memebers
*/
function users_with_open_entries ()
{
$users = array ();
$this -> db -> select ( $this -> info_table , 'DISTINCT info_owner' , array (
str_replace ( ' AND ' , '' , $this -> statusFilter ( 'open' )),
'(ABS(info_startdate-' . time () . ')<' . ( 4 * 24 * 60 * 60 ) . ' OR ' . // start_day within 4 days
'ABS(info_enddate-' . time () . ')<' . ( 4 * 24 * 60 * 60 ) . ')' , // end_day within 4 days
), __LINE__ , __FILE__ );
while ( $this -> db -> next_record ())
{
$users [] = $this -> db -> f ( 0 );
}
$this -> db -> select ( $this -> info_table , 'DISTINCT info_responsible' , $this -> statusFilter ( 'open' , false ), __LINE__ , __FILE__ );
while ( $this -> db -> next_record ())
{
foreach ( explode ( ',' , $this -> db -> f ( 0 )) as $responsible )
{
if ( $GLOBALS [ 'egw' ] -> accounts -> get_type ( $responsible ) == 'g' )
{
$responsible = $GLOBALS [ 'egw' ] -> accounts -> members ( $responsible , true );
}
if ( $responsible )
{
foreach ( is_array ( $responsible ) ? $responsible : array ( $responsible ) as $user )
{
if ( $user && ! in_array ( $user , $users )) $users [] = $user ;
}
}
}
}
return $users ;
}
2006-10-04 19:40:33 +02:00
}