mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-14 18:08:21 +01:00
move egw_link to Api\Link
This commit is contained in:
parent
614f75fd26
commit
0ba4283f9f
@ -18,7 +18,6 @@ namespace EGroupware\Api;
|
|||||||
|
|
||||||
// explicitly reference classes still in phpgwapi
|
// explicitly reference classes still in phpgwapi
|
||||||
use categories;
|
use categories;
|
||||||
use egw_link;
|
|
||||||
|
|
||||||
use calendar_bo; // to_do: do NOT require it, just use if there
|
use calendar_bo; // to_do: do NOT require it, just use if there
|
||||||
|
|
||||||
@ -813,11 +812,11 @@ class Contacts extends Contacts\Storage
|
|||||||
$delete['tid'] = self::DELETED_TYPE;
|
$delete['tid'] = self::DELETED_TYPE;
|
||||||
if ($check_etag) $delete['etag'] = $check_etag;
|
if ($check_etag) $delete['etag'] = $check_etag;
|
||||||
if (($ok = $this->save($delete))) $ok = true; // we have to return true or false
|
if (($ok = $this->save($delete))) $ok = true; // we have to return true or false
|
||||||
egw_link::unlink(0,'addressbook',$id,'','','',true);
|
Link::unlink(0,'addressbook',$id,'','','',true);
|
||||||
}
|
}
|
||||||
elseif (($ok = parent::delete($id,$check_etag)))
|
elseif (($ok = parent::delete($id,$check_etag)))
|
||||||
{
|
{
|
||||||
egw_link::unlink(0,'addressbook',$id);
|
Link::unlink(0,'addressbook',$id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't notify of final purge
|
// Don't notify of final purge
|
||||||
@ -996,12 +995,12 @@ class Contacts extends Contacts\Storage
|
|||||||
$GLOBALS['egw']->hooks->process($to_write,False,True); // called for every app now, not only enabled ones));
|
$GLOBALS['egw']->hooks->process($to_write,False,True); // called for every app now, not only enabled ones));
|
||||||
}
|
}
|
||||||
// Notify linked apps about changes in the contact data
|
// Notify linked apps about changes in the contact data
|
||||||
egw_link::notify_update('addressbook', $contact['id'], $contact);
|
Link::notify_update('addressbook', $contact['id'], $contact);
|
||||||
|
|
||||||
// Check for restore of deleted contact, restore held links
|
// Check for restore of deleted contact, restore held links
|
||||||
if($old && $old['tid'] == self::DELETED_TYPE && $contact['tid'] != self::DELETED_TYPE)
|
if($old && $old['tid'] == self::DELETED_TYPE && $contact['tid'] != self::DELETED_TYPE)
|
||||||
{
|
{
|
||||||
egw_link::restore('addressbook', $contact['id']);
|
Link::restore('addressbook', $contact['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record change history for sql - doesn't work for LDAP accounts
|
// Record change history for sql - doesn't work for LDAP accounts
|
||||||
@ -1805,11 +1804,11 @@ class Contacts extends Contacts\Storage
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
foreach(egw_link::get_links('addressbook',$contact['id']) as $data)
|
foreach(Link::get_links('addressbook',$contact['id']) as $data)
|
||||||
{
|
{
|
||||||
//_debug_array(array('function'=>__METHOD__,'line'=>__LINE__,'app'=>'addressbook','id'=>$contact['id'],'data:'=>$data,'target'=>$target['id']));
|
//_debug_array(array('function'=>__METHOD__,'line'=>__LINE__,'app'=>'addressbook','id'=>$contact['id'],'data:'=>$data,'target'=>$target['id']));
|
||||||
// info_from and info_link_id (main link)
|
// info_from and info_link_id (main link)
|
||||||
$newlinkID = egw_link::link('addressbook',$target['id'],$data['app'],$data['id'],$data['remark'],$target['owner']);
|
$newlinkID = Link::link('addressbook',$target['id'],$data['app'],$data['id'],$data['remark'],$target['owner']);
|
||||||
//_debug_array(array('newLinkID'=>$newlinkID));
|
//_debug_array(array('newLinkID'=>$newlinkID));
|
||||||
if ($newlinkID)
|
if ($newlinkID)
|
||||||
{
|
{
|
||||||
|
1732
api/src/Link.php
Normal file
1732
api/src/Link.php
Normal file
File diff suppressed because it is too large
Load Diff
483
api/src/Link/Storage.php
Normal file
483
api/src/Link/Storage.php
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EGroupware API - Interapplicaton links storage
|
||||||
|
*
|
||||||
|
* Links have two ends each pointing to an entry, each entry is a double:
|
||||||
|
* - app app-name or directory-name of an egw application, eg. 'infolog'
|
||||||
|
* - id this is the id, eg. an integer or a tupple like '0:INBOX:1234'
|
||||||
|
*
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||||
|
* @copyright 2001-2016 by RalfBecker@outdoor-training.de
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package api
|
||||||
|
* @subpackage link
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace EGroupware\Api\Link;
|
||||||
|
|
||||||
|
use EGroupware\Api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generalized linking between entries of eGroupware apps - SO layer
|
||||||
|
*
|
||||||
|
* All vars passed to this class get correct escaped to prevent query insertion.
|
||||||
|
*
|
||||||
|
* All methods are now static!
|
||||||
|
*/
|
||||||
|
class Storage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Name of the links table
|
||||||
|
*/
|
||||||
|
const TABLE = 'egw_links';
|
||||||
|
/**
|
||||||
|
* Turns on debug-messages
|
||||||
|
*/
|
||||||
|
const DEBUG = false;
|
||||||
|
/**
|
||||||
|
* Reference to the global db-class
|
||||||
|
*
|
||||||
|
* @var egw_db
|
||||||
|
*/
|
||||||
|
private static $db;
|
||||||
|
/**
|
||||||
|
* True if call to get_links or get_3links exceeded limit (contains not all rows)
|
||||||
|
*/
|
||||||
|
public static $limit_exceeded = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creats a link between $app1,$id1 and $app2,$id2
|
||||||
|
*
|
||||||
|
* @param string $app1 appname of 1. endpoint of the link
|
||||||
|
* @param string $id1 id in $app1
|
||||||
|
* @param string $app2 appname of 2. endpoint of the link
|
||||||
|
* @param string $id2 id in $app2
|
||||||
|
* @param string $remark ='' Remark to be saved with the link (defaults to '')
|
||||||
|
* @param int $owner =0 Owner of the link (defaults to user)
|
||||||
|
* @param int $lastmod =0 timestamp of last modification (defaults to now=time())
|
||||||
|
* @return int/boolean False (for db or param-error) or on success link_id (Please not the return-value of $id1)
|
||||||
|
*/
|
||||||
|
static function link( $app1,&$id1,$app2,$id2='',$remark='',$owner=0,$lastmod=0 )
|
||||||
|
{
|
||||||
|
if (self::DEBUG)
|
||||||
|
{
|
||||||
|
echo "<p>solink.link('$app1',$id1,'$app2',$id2,'$remark',$owner)</p>\n";
|
||||||
|
}
|
||||||
|
if ($app1 == $app2 && $id1 == $id2 ||
|
||||||
|
$id1 == '' || $id2 == '' || $app1 == '' || $app2 == '')
|
||||||
|
{
|
||||||
|
return False; // dont link to self or other nosense
|
||||||
|
}
|
||||||
|
if (($link = self::get_link($app1,$id1,$app2,$id2)))
|
||||||
|
{
|
||||||
|
if ($link['link_remark'] != $remark)
|
||||||
|
{
|
||||||
|
self::update_remark($link['link_id'],$remark);
|
||||||
|
}
|
||||||
|
return $link['link_id']; // link alread exist
|
||||||
|
}
|
||||||
|
if (!$owner)
|
||||||
|
{
|
||||||
|
$owner = $GLOBALS['egw_info']['user']['account_id'];
|
||||||
|
}
|
||||||
|
return self::$db->insert(self::TABLE,array(
|
||||||
|
'link_app1' => $app1,
|
||||||
|
'link_id1' => $id1,
|
||||||
|
'link_app2' => $app2,
|
||||||
|
'link_id2' => $id2,
|
||||||
|
'link_remark' => $remark,
|
||||||
|
'link_lastmod' => $lastmod ? $lastmod : time(),
|
||||||
|
'link_owner' => $owner,
|
||||||
|
),False,__LINE__,__FILE__) ? self::$db->get_last_insert_id(self::TABLE,'link_id') : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update the remark of a link
|
||||||
|
*
|
||||||
|
* @param int $link_id link to update
|
||||||
|
* @param string $remark new text for the remark
|
||||||
|
* @return boolean true on success, else false
|
||||||
|
*/
|
||||||
|
static function update_remark($link_id,$remark)
|
||||||
|
{
|
||||||
|
return self::$db->update(self::TABLE,array(
|
||||||
|
'link_remark' => $remark,
|
||||||
|
'link_lastmod' => time(),
|
||||||
|
),array(
|
||||||
|
'link_id' => $link_id,
|
||||||
|
),__LINE__,__FILE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns array of links to $app,$id
|
||||||
|
*
|
||||||
|
* @param string $app appname
|
||||||
|
* @param string|array $id id(s) in $app
|
||||||
|
* @param string $only_app ='' if set return only links from $only_app (eg. only addressbook-entries) or NOT from if $only_app[0]=='!'
|
||||||
|
* @param string $order ='link_lastmod DESC' defaults to newest links first
|
||||||
|
* @param boolean $deleted =false Include links that have been flagged as deleted, waiting for purge of linked record.
|
||||||
|
* @param int|array $limit =null number of entries to return, default null = all or array(offset, num_rows) to return num_rows starting from offset
|
||||||
|
* @return array id => links pairs if $id is an array or just the links (only_app: ids) or empty array if no matching links found
|
||||||
|
*/
|
||||||
|
static function get_links($app, $id, $only_app='', $order='link_lastmod DESC', $deleted=false, $limit=null)
|
||||||
|
{
|
||||||
|
if (self::DEBUG)
|
||||||
|
{
|
||||||
|
echo "<p>solink.get_links($app,".print_r($id,true).",$only_app,$order,$deleted)</p>\n";
|
||||||
|
}
|
||||||
|
if (($not_only = $only_app[0] == '!'))
|
||||||
|
{
|
||||||
|
$only_app = substr($only_app,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset = false;
|
||||||
|
if (is_array($limit))
|
||||||
|
{
|
||||||
|
list($offset, $limit) = $limit;
|
||||||
|
}
|
||||||
|
elseif($limit)
|
||||||
|
{
|
||||||
|
$offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$links = array();
|
||||||
|
try {
|
||||||
|
foreach(self::$db->select(self::TABLE, '*', self::$db->expression(self::TABLE, '((', array(
|
||||||
|
'link_app1' => $app,
|
||||||
|
'link_id1' => $id,
|
||||||
|
),') OR (',array(
|
||||||
|
'link_app2' => $app,
|
||||||
|
'link_id2' => $id,
|
||||||
|
),'))',
|
||||||
|
$deleted ? '' : ' AND deleted IS NULL'
|
||||||
|
), __LINE__, __FILE__, $offset, $order ? " ORDER BY $order" : '', 'phpgwapi', $limit) as $row)
|
||||||
|
{
|
||||||
|
// check if left side (1) is one of our targets --> add it
|
||||||
|
if ($row['link_app1'] == $app && in_array($row['link_id1'],(array)$id))
|
||||||
|
{
|
||||||
|
self::_add2links($row,true,$only_app,$not_only,$links);
|
||||||
|
}
|
||||||
|
// check if right side (2) is one of our targets --> add it (both can be true for multiple targets!)
|
||||||
|
if ($row['link_app2'] == $app && in_array($row['link_id2'],(array)$id))
|
||||||
|
{
|
||||||
|
self::_add2links($row,false,$only_app,$not_only,$links);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if query returns exactly limit rows, we assume there are more and therefore set self::$limit_exceeded
|
||||||
|
self::$limit_exceeded = $offset !== false && count(is_array($id) ? $links : $links[$id]) == $limit;
|
||||||
|
}
|
||||||
|
// catch Illegal mix of collations (ascii_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' (1267)
|
||||||
|
// caused by non-ascii chars compared with ascii field uid
|
||||||
|
catch(Api\Db\Exception $e) {
|
||||||
|
_egw_log_exception($e);
|
||||||
|
}
|
||||||
|
return is_array($id) ? $links : ($links[$id] ? $links[$id] : array());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function _add2links($row,$left,$only_app,$not_only,array &$links)
|
||||||
|
{
|
||||||
|
$linked_app = $left ? $row['link_app2'] : $row['link_app1'];
|
||||||
|
$linked_id = $left ? $row['link_id2'] : $row['link_id1'];
|
||||||
|
$app_id = $left ? $row['link_id1'] : $row['link_id2'];
|
||||||
|
list($app) = explode('-',$linked_app);
|
||||||
|
if ($only_app && $not_only == ($linked_app == $only_app) || !$GLOBALS['egw_info']['user']['apps'][$app])
|
||||||
|
{
|
||||||
|
#echo "$linked_app == $only_app, ";var_dump($linked_app == $only_app);echo " ->dont return a link<br>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#echo "returning ".(($only_app && !$not_only) ? " linkid:".$linked_id : " full array with linkid $linked_id")."<br>";
|
||||||
|
$links[$app_id][$row['link_id']] = ($only_app && !$not_only) ? $linked_id : array(
|
||||||
|
'app' => $linked_app,
|
||||||
|
'id' => $linked_id,
|
||||||
|
'remark' => $row['link_remark'],
|
||||||
|
'owner' => $row['link_owner'],
|
||||||
|
'lastmod' => $row['link_lastmod'],
|
||||||
|
'link_id' => $row['link_id'],
|
||||||
|
'deleted' => $row['deleted'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns data of a link
|
||||||
|
*
|
||||||
|
* @param ing/string $app_link_id > 0 link_id of link or app-name of link
|
||||||
|
* @param string $id ='' id in $app, if no integer link_id given in $app_link_id
|
||||||
|
* @param string $app2 ='' appname of 2. endpoint of the link, if no integer link_id given in $app_link_id
|
||||||
|
* @param string $id2 ='' id in $app2, if no integer link_id given in $app_link_id
|
||||||
|
* @return array with link-data or False
|
||||||
|
*/
|
||||||
|
static function get_link($app_link_id,$id='',$app2='',$id2='')
|
||||||
|
{
|
||||||
|
if (self::DEBUG)
|
||||||
|
{
|
||||||
|
echo "<p>solink.get_link('$app_link_id',$id,'$app2','$id2')</p>\n";
|
||||||
|
}
|
||||||
|
if ((int) $app_link_id > 0)
|
||||||
|
{
|
||||||
|
$where = array('link_id' => $app_link_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($app_link_id == '' || $id == '' || $app2 == '' || $id2 == '')
|
||||||
|
{
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
$where = self::$db->expression(self::TABLE,'(',array(
|
||||||
|
'link_app1' => $app_link_id,
|
||||||
|
'link_id1' => $id,
|
||||||
|
'link_app2' => $app2,
|
||||||
|
'link_id2' => $id2,
|
||||||
|
),') OR (',array(
|
||||||
|
'link_app2' => $app_link_id,
|
||||||
|
'link_id2' => $id,
|
||||||
|
'link_app1' => $app2,
|
||||||
|
'link_id1' => $id2,
|
||||||
|
),')');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return self::$db->select(self::TABLE,'*',$where,__LINE__,__FILE__)->fetch(ADODB_FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
// catch Illegal mix of collations (ascii_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' (1267)
|
||||||
|
// caused by non-ascii chars compared with ascii field uid
|
||||||
|
catch(Api\Db\Exception $e) {
|
||||||
|
_egw_log_exception($e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove link with $link_id or all links matching given params
|
||||||
|
*
|
||||||
|
* @param $link_id link-id to remove if > 0
|
||||||
|
* @param string $app ='' app-name of links to remove
|
||||||
|
* @param string $id ='' id in $app or '' remove all links from $app
|
||||||
|
* @param int $owner =0 account_id to delete all links of a given owner, or 0
|
||||||
|
* @param string $app2 ='' appname of 2. endpoint of the link
|
||||||
|
* @param string $id2 ='' id in $app2
|
||||||
|
* @param boolean $hold_for_purge Don't really delete the link, just mark it as deleted and wait for final delete of linked entry
|
||||||
|
* @return array with deleted links
|
||||||
|
*/
|
||||||
|
static function unlink($link_id,$app='',$id='',$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
||||||
|
{
|
||||||
|
if (self::DEBUG)
|
||||||
|
{
|
||||||
|
echo "<p>solink.unlink($link_id,$app,$id,$owner,$app2,$id2)</p>\n";
|
||||||
|
}
|
||||||
|
if ((int)$link_id > 0)
|
||||||
|
{
|
||||||
|
$where = array('link_id' => $link_id);
|
||||||
|
}
|
||||||
|
elseif ($app == '' AND $owner == '')
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($app != '' && $app2 == '')
|
||||||
|
{
|
||||||
|
$check1 = array('link_app1' => $app);
|
||||||
|
$check2 = array('link_app2' => $app);
|
||||||
|
if ($id != '')
|
||||||
|
{
|
||||||
|
$check1['link_id1'] = $id;
|
||||||
|
$check2['link_id2'] = $id;
|
||||||
|
}
|
||||||
|
$where = self::$db->expression(self::TABLE,'((',$check1,') OR (',$check2,'))');
|
||||||
|
}
|
||||||
|
elseif ($app != '' && $app2 != '')
|
||||||
|
{
|
||||||
|
$where = self::$db->expression(self::TABLE,'(',array(
|
||||||
|
'link_app1' => $app,
|
||||||
|
'link_id1' => $id,
|
||||||
|
'link_app2' => $app2,
|
||||||
|
'link_id2' => $id2,
|
||||||
|
),') OR (',array(
|
||||||
|
'link_app1' => $app2,
|
||||||
|
'link_id1' => $id2,
|
||||||
|
'link_app2' => $app,
|
||||||
|
'link_id2' => $id,
|
||||||
|
),')');
|
||||||
|
}
|
||||||
|
if ($owner)
|
||||||
|
{
|
||||||
|
if ($app) $where = array($where);
|
||||||
|
$where['link_owner'] = $owner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$deleted = array();
|
||||||
|
try {
|
||||||
|
foreach(self::$db->select(self::TABLE,'*',$where,__LINE__,__FILE__) as $row)
|
||||||
|
{
|
||||||
|
$deleted[] = $row;
|
||||||
|
}
|
||||||
|
if($hold_for_purge)
|
||||||
|
{
|
||||||
|
self::$db->update(self::TABLE,array(
|
||||||
|
'deleted' => time(),
|
||||||
|
'link_lastmod' => time(),
|
||||||
|
), $where, __LINE__,__FILE__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self::$db->delete(self::TABLE,$where,__LINE__,__FILE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// catch Illegal mix of collations (ascii_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' (1267)
|
||||||
|
// caused by non-ascii chars compared with ascii field uid
|
||||||
|
catch(Api\Db\Exception $e) {
|
||||||
|
_egw_log_exception($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore links being held as deleted waiting for purge of linked record (un-delete)
|
||||||
|
*
|
||||||
|
* @param string $app ='' app-name of links to remove
|
||||||
|
* @param string $id ='' id in $app or '' remove all links from $app
|
||||||
|
*/
|
||||||
|
static function restore($app, $id)
|
||||||
|
{
|
||||||
|
if (self::DEBUG)
|
||||||
|
{
|
||||||
|
echo "<p>solink.restore($app,$id)</p>\n";
|
||||||
|
}
|
||||||
|
if ($app == '')
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$check1 = array('link_app1' => $app);
|
||||||
|
$check2 = array('link_app2' => $app);
|
||||||
|
if ($id != '')
|
||||||
|
{
|
||||||
|
$check1['link_id1'] = $id;
|
||||||
|
$check2['link_id2'] = $id;
|
||||||
|
}
|
||||||
|
$where = self::$db->expression(self::TABLE,'((',$check1,') OR (',$check2,'))');
|
||||||
|
self::$db->update(self::TABLE,array('deleted'=> null), $where, __LINE__,__FILE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes ownership of all links from $owner to $new_owner
|
||||||
|
*
|
||||||
|
* This is needed when a user/account gets deleted
|
||||||
|
* Does NOT change the modification-time
|
||||||
|
*
|
||||||
|
* @param int $owner acount_id of owner to change
|
||||||
|
* @param int $new_owner account_id of new owner
|
||||||
|
* @return int number of links changed
|
||||||
|
*/
|
||||||
|
static function chown($owner,$new_owner)
|
||||||
|
{
|
||||||
|
if ((int)$owner <= 0 || (int) $new_owner <= 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self::$db->update(self::TABLE,array('owner'=>$new_owner),array('owner'=>$owner),__LINE__,__FILE__);
|
||||||
|
|
||||||
|
return self::$db->affected_rows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all links from a given app's entries to an other app's entries, which both link to the same 3. app and id
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* I search all timesheet's linked to a given project and id(s), who are also linked to other entries,
|
||||||
|
* which link to the same project:
|
||||||
|
*
|
||||||
|
* ($app='timesheet'/some id) <--a--> (other app/other id) <--b--> ($t_app='projectmanager'/$t_id=$pm_id)
|
||||||
|
* ^ ^
|
||||||
|
* +---------------------------c-----------------------------------------+
|
||||||
|
*
|
||||||
|
* Api\Link::get_3links('timesheet','projectmanager',$pm_id) returns the links (c) between the timesheet and the project,
|
||||||
|
* plus the other app/id in the keys 'app3' and 'id3'
|
||||||
|
*
|
||||||
|
* @param string $app app the returned links are linked on one side (atm. this must be link_app1!)
|
||||||
|
* @param string $target_app app the returned links other side link also to
|
||||||
|
* @param string|array $target_id =null id(s) the returned links other side link also to
|
||||||
|
* @param boolean $just_app_ids =false return array with link_id => app_id pairs, not the full link record
|
||||||
|
* @param string $order ='link_lastmod DESC' defaults to newest links first
|
||||||
|
* @param int|array $limit =null number of entries to return, default null = all or array(offset, num_rows) to return num_rows starting from offset
|
||||||
|
* @return array with links from entries from $app to $target_app/$target_id plus the other (b) link_id/app/id in the keys 'link3'/'app3'/'id3'
|
||||||
|
*/
|
||||||
|
static function get_3links($app, $target_app, $target_id=null, $just_app_ids=false, $order='link_lastmod DESC', $limit=null)
|
||||||
|
{
|
||||||
|
$table = self::TABLE;
|
||||||
|
$arrayofselects=array(
|
||||||
|
// retrieve the type of links, where the relation is realized as timesheet->infolog/tracker via infolog->projectmanager to timesheet->projectmanager
|
||||||
|
array('table'=>self::TABLE,
|
||||||
|
'cols'=>'c.*,b.link_app1 AS app3,b.link_id1 AS id3,b.link_id AS link3',
|
||||||
|
'where'=>'a.link_app1='.self::$db->quote($app).' AND c.link_app2='.self::$db->quote($target_app).
|
||||||
|
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND c.',array('link_id2' => $target_id))),
|
||||||
|
'join'=>" a
|
||||||
|
JOIN $table b ON a.link_id2=b.link_id1 AND a.link_app2=b.link_app1
|
||||||
|
JOIN $table c ON a.link_id1=c.link_id1 AND a.link_app1=c.link_app1 AND a.link_id!=c.link_id AND c.link_app2=b.link_app2 AND c.link_id2=b.link_id2",
|
||||||
|
),
|
||||||
|
// retrieve the type of links, where the relation is realized as timesheet->infolog/tracker and projectmanager->timesheet
|
||||||
|
array('table'=>self::TABLE,
|
||||||
|
'cols'=>'b.link_id, b.link_app2 as app1, b.link_id2 as id1, b.link_app1 as app2, b.link_id1 as id2, b.link_remark,b.link_lastmod,b.link_owner,b.deleted,c.link_app1 AS app3,c.link_id1 AS id3,c.link_id AS link3',
|
||||||
|
'where'=>'a.link_app1='.self::$db->quote($app).' AND b.link_app1='.self::$db->quote($target_app).
|
||||||
|
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND b.',array('link_id1' => $target_id))),
|
||||||
|
'join'=>" a
|
||||||
|
JOIN $table b ON a.link_id1=b.link_id2 AND a.link_app1=b.link_app2
|
||||||
|
JOIN $table c ON a.link_id2=c.link_id1 AND a.link_app2=c.link_app1 AND a.link_id!=c.link_id AND c.link_app2=b.link_app1 AND c.link_id2=b.link_id1",
|
||||||
|
),
|
||||||
|
// retrieve the type of links, where the relation is realized as timesheet->projectmanager and infolog->timesheet
|
||||||
|
array('table'=>self::TABLE,
|
||||||
|
'cols'=>'a.*,c.link_app1 AS app3,c.link_id1 AS id3,c.link_id AS link3',
|
||||||
|
'where'=>'a.link_app1='.self::$db->quote($app).' AND a.link_app2='.self::$db->quote($target_app).
|
||||||
|
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND a.',array('link_id2' => $target_id))),
|
||||||
|
'join'=>" a
|
||||||
|
JOIN $table b ON a.link_id1=b.link_id2 AND a.link_app1=b.link_app2
|
||||||
|
JOIN $table c ON a.link_id2=c.link_id2 AND a.link_app2=c.link_app2 AND a.link_id!=c.link_id AND c.link_app1=b.link_app1 AND c.link_id1=b.link_id1",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$offset = false;
|
||||||
|
if (is_array($limit))
|
||||||
|
{
|
||||||
|
list($offset, $limit) = $limit;
|
||||||
|
}
|
||||||
|
elseif($limit)
|
||||||
|
{
|
||||||
|
$offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$links = array();
|
||||||
|
foreach(self::$db->union($arrayofselects, __LINE__, __FILE__, $order, $offset, $limit) as $row)
|
||||||
|
{
|
||||||
|
if ($just_app_ids)
|
||||||
|
{
|
||||||
|
if ($row['link_app1'] == $target_app && (is_null($target_id) || in_array($row['link_id1'],(array)$target_id)))
|
||||||
|
{
|
||||||
|
$links[$row['link_id']] = $row['link_id2'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$links[$row['link_id']] = $row['link_id1'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$links[] = Api\Db::strip_array_keys($row,'link_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if query returns exactly limit rows, we assume there are more and therefore set self::$limit_exceeded
|
||||||
|
self::$limit_exceeded = $offset !== false && count($links) == $limit;
|
||||||
|
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise our static vars
|
||||||
|
*/
|
||||||
|
static function init_static( )
|
||||||
|
{
|
||||||
|
self::$db = $GLOBALS['egw']->db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Storage::init_static();
|
@ -14,9 +14,6 @@ namespace EGroupware\Api\Storage;
|
|||||||
|
|
||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
|
|
||||||
// explicitly reference classes still in phpgwapi
|
|
||||||
use egw_link;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Managing custom-field definitions
|
* Managing custom-field definitions
|
||||||
*/
|
*/
|
||||||
@ -248,7 +245,7 @@ class Customfields implements \IteratorAggregate
|
|||||||
{
|
{
|
||||||
$app = $field['type'];
|
$app = $field['type'];
|
||||||
}
|
}
|
||||||
if ($value) $value = egw_link::title($app, $value);
|
if ($value) $value = Api\Link::title($app, $value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -301,7 +298,7 @@ class Customfields implements \IteratorAggregate
|
|||||||
|
|
||||||
if (is_null($link_types))
|
if (is_null($link_types))
|
||||||
{
|
{
|
||||||
$link_types = array_keys(array_intersect(egw_link::app_list('query'),egw_link::app_list('title')));
|
$link_types = array_keys(array_intersect(Api\Link::app_list('query'),Api\Link::app_list('title')));
|
||||||
$link_types[] = 'link-entry';
|
$link_types[] = 'link-entry';
|
||||||
}
|
}
|
||||||
return $link_types;
|
return $link_types;
|
||||||
@ -338,7 +335,7 @@ class Customfields implements \IteratorAggregate
|
|||||||
$app = $data['type'];
|
$app = $data['type'];
|
||||||
$id = $old['#'.$name];
|
$id = $old['#'.$name];
|
||||||
}
|
}
|
||||||
egw_link::unlink(false,$own_app,$values[$id_name],'',$app,$id);
|
Api\Link::unlink(false,$own_app,$values[$id_name],'',$app,$id);
|
||||||
}
|
}
|
||||||
if ($data['type'] == 'link-entry')
|
if ($data['type'] == 'link-entry')
|
||||||
{
|
{
|
||||||
@ -351,7 +348,7 @@ class Customfields implements \IteratorAggregate
|
|||||||
}
|
}
|
||||||
if ($id) // create new link, does nothing for already existing links
|
if ($id) // create new link, does nothing for already existing links
|
||||||
{
|
{
|
||||||
egw_link::link($own_app,$values[$id_name],$app,$id);
|
Api\Link::link($own_app,$values[$id_name],$app,$id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ namespace EGroupware\Api\Storage;
|
|||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
|
|
||||||
// explicitly reference classes still in phpgwapi
|
// explicitly reference classes still in phpgwapi
|
||||||
use egw_link;
|
|
||||||
use html;
|
use html;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,7 +194,7 @@ abstract class Tracking
|
|||||||
{
|
{
|
||||||
if ($cf_app)
|
if ($cf_app)
|
||||||
{
|
{
|
||||||
$linkable_cf_types = array('link-entry')+array_keys(egw_link::app_list());
|
$linkable_cf_types = array('link-entry')+array_keys(Api\Link::app_list());
|
||||||
foreach(Customfields::get($cf_app, true) as $cf_name => $cf_data)
|
foreach(Customfields::get($cf_app, true) as $cf_name => $cf_data)
|
||||||
{
|
{
|
||||||
$this->field2history['#'.$cf_name] = '#'.$cf_name;
|
$this->field2history['#'.$cf_name] = '#'.$cf_name;
|
||||||
@ -357,9 +356,9 @@ abstract class Tracking
|
|||||||
}
|
}
|
||||||
$source_id = $data[$this->id_field];
|
$source_id = $data[$this->id_field];
|
||||||
//error_log(__METHOD__.__LINE__.array2string($source_id));
|
//error_log(__METHOD__.__LINE__.array2string($source_id));
|
||||||
if ($source_id) egw_link::link($this->app,$source_id,$app,$id);
|
if ($source_id) Api\Link::link($this->app,$source_id,$app,$id);
|
||||||
//error_log(__METHOD__.__LINE__."egw_link::link('$this->app',".array2string($source_id).",'$app',$id);");
|
//error_log(__METHOD__.__LINE__."Api\Link::link('$this->app',".array2string($source_id).",'$app',$id);");
|
||||||
//echo "<p>egw_link::link('$this->app',{$data[$this->id_field]},'$app',$id);</p>\n";
|
//echo "<p>Api\Link::link('$this->app',{$data[$this->id_field]},'$app',$id);</p>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlink removed application entries
|
// unlink removed application entries
|
||||||
@ -372,8 +371,8 @@ abstract class Tracking
|
|||||||
if (!$id) continue;
|
if (!$id) continue;
|
||||||
}
|
}
|
||||||
$source_id = $data[$this->id_field];
|
$source_id = $data[$this->id_field];
|
||||||
if ($source_id) egw_link::unlink(null,$this->app,$source_id,0,$app,$id);
|
if ($source_id) Api\Link::unlink(null,$this->app,$source_id,0,$app,$id);
|
||||||
//echo "<p>egw_link::unlink(NULL,'$this->app',{$data[$this->id_field]},0,'$app',$id);</p>\n";
|
//echo "<p>Api\Link::unlink(NULL,'$this->app',{$data[$this->id_field]},0,'$app',$id);</p>\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,7 +868,7 @@ abstract class Tracking
|
|||||||
{
|
{
|
||||||
unset($old); // not used, but required by function signature
|
unset($old); // not used, but required by function signature
|
||||||
|
|
||||||
return egw_link::title($this->app,$data[$this->id_field]);
|
return Api\Link::title($this->app,$data[$this->id_field]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -887,7 +886,7 @@ abstract class Tracking
|
|||||||
{
|
{
|
||||||
unset($old, $deleted, $receiver); // not used, but required by function signature
|
unset($old, $deleted, $receiver); // not used, but required by function signature
|
||||||
|
|
||||||
return egw_link::title($this->app,$data[$this->id_field]);
|
return Api\Link::title($this->app,$data[$this->id_field]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -932,10 +931,10 @@ abstract class Tracking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (($view = egw_link::view($this->app,$data[$this->id_field])))
|
if (($view = Api\Link::view($this->app,$data[$this->id_field])))
|
||||||
{
|
{
|
||||||
$link = $GLOBALS['egw']->link('/index.php',$view);
|
$link = $GLOBALS['egw']->link('/index.php',$view);
|
||||||
$popup = egw_link::is_popup($this->app,'view');
|
$popup = Api\Link::is_popup($this->app,'view');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($link[0] == '/')
|
if ($link[0] == '/')
|
||||||
@ -966,14 +965,14 @@ abstract class Tracking
|
|||||||
{
|
{
|
||||||
unset($receiver); // not used, but required by function signature
|
unset($receiver); // not used, but required by function signature
|
||||||
|
|
||||||
if (($view = egw_link::view($this->app,$data[$this->id_field])))
|
if (($view = Api\Link::view($this->app,$data[$this->id_field])))
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'text' => $this->get_title($data,$old),
|
'text' => $this->get_title($data,$old),
|
||||||
'app' => $this->app,
|
'app' => $this->app,
|
||||||
'id' => $data[$this->id_field],
|
'id' => $data[$this->id_field],
|
||||||
'view' => $view,
|
'view' => $view,
|
||||||
'popup' => egw_link::is_popup($this->app,'view'),
|
'popup' => Api\Link::is_popup($this->app,'view'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
namespace EGroupware\Api\Vfs\Links;
|
namespace EGroupware\Api\Vfs\Links;
|
||||||
|
|
||||||
use EGroupware\Api\Vfs;
|
use EGroupware\Api\Vfs;
|
||||||
|
use EGroupware\Api;
|
||||||
|
|
||||||
// explicitly import old phpgwapi classes used:
|
// explicitly import old phpgwapi classes used:
|
||||||
use egw_link;
|
|
||||||
use addressbook_vcal;
|
use addressbook_vcal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,10 +111,10 @@ class StreamWrapper extends LinksParent
|
|||||||
// which gives him then read AND write access to the file store of the entry
|
// which gives him then read AND write access to the file store of the entry
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// vfs & stream-wrapper use posix rights, egw_link::file_access uses EGW_ACL_{EDIT|READ}!
|
// vfs & stream-wrapper use posix rights, Api\Link::file_access uses EGW_ACL_{EDIT|READ}!
|
||||||
$required = $check & Vfs::WRITABLE ? EGW_ACL_EDIT : EGW_ACL_READ;
|
$required = $check & Vfs::WRITABLE ? EGW_ACL_EDIT : EGW_ACL_READ;
|
||||||
$access = egw_link::file_access($app,$id,$required,$rel_path,Vfs::$user);
|
$access = Api\Link::file_access($app,$id,$required,$rel_path,Vfs::$user);
|
||||||
$what = "from egw_link::file_access('$app',$id,$required,'$rel_path,".Vfs::$user.")";
|
$what = "from Api\Link::file_access('$app',$id,$required,'$rel_path,".Vfs::$user.")";
|
||||||
}
|
}
|
||||||
if (self::DEBUG) error_log(__METHOD__."($url,$check) user=".Vfs::$user." ($what) ".($access?"access granted ($app:$id:$rel_path)":'no access!!!'));
|
if (self::DEBUG) error_log(__METHOD__."($url,$check) user=".Vfs::$user." ($what) ".($access?"access granted ($app:$id:$rel_path)":'no access!!!'));
|
||||||
return $access;
|
return $access;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* API - Interapplicaton links BO layer
|
* EGroupware API - Interapplicaton links storage
|
||||||
*
|
*
|
||||||
* Links have two ends each pointing to an entry, each entry is a double:
|
* Links have two ends each pointing to an entry, each entry is a double:
|
||||||
* - app app-name or directory-name of an egw application, eg. 'infolog'
|
* - app app-name or directory-name of an egw application, eg. 'infolog'
|
||||||
@ -8,472 +8,18 @@
|
|||||||
*
|
*
|
||||||
* @link http://www.egroupware.org
|
* @link http://www.egroupware.org
|
||||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||||
* @copyright 2001-2015 by RalfBecker@outdoor-training.de
|
* @copyright 2001-2016 by RalfBecker@outdoor-training.de
|
||||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
* @package api
|
* @package api
|
||||||
* @subpackage link
|
* @subpackage link
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use EGroupware\Api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generalized linking between entries of eGroupware apps - SO layer
|
* generalized linking between entries of eGroupware apps - SO layer
|
||||||
*
|
*
|
||||||
* All vars passed to this class get correct escaped to prevent query insertion.
|
* @deprecated use Api\Link\Storage
|
||||||
*
|
|
||||||
* All methods are now static!
|
|
||||||
*/
|
*/
|
||||||
class solink
|
class solink extends Api\Link\Storage {}
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Name of the links table
|
|
||||||
*/
|
|
||||||
const TABLE = 'egw_links';
|
|
||||||
/**
|
|
||||||
* Turns on debug-messages
|
|
||||||
*/
|
|
||||||
const DEBUG = false;
|
|
||||||
/**
|
|
||||||
* Reference to the global db-class
|
|
||||||
*
|
|
||||||
* @var egw_db
|
|
||||||
*/
|
|
||||||
private static $db;
|
|
||||||
/**
|
|
||||||
* True if call to get_links or get_3links exceeded limit (contains not all rows)
|
|
||||||
*/
|
|
||||||
public static $limit_exceeded = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creats a link between $app1,$id1 and $app2,$id2
|
|
||||||
*
|
|
||||||
* @param string $app1 appname of 1. endpoint of the link
|
|
||||||
* @param string $id1 id in $app1
|
|
||||||
* @param string $app2 appname of 2. endpoint of the link
|
|
||||||
* @param string $id2 id in $app2
|
|
||||||
* @param string $remark ='' Remark to be saved with the link (defaults to '')
|
|
||||||
* @param int $owner =0 Owner of the link (defaults to user)
|
|
||||||
* @param int $lastmod =0 timestamp of last modification (defaults to now=time())
|
|
||||||
* @return int/boolean False (for db or param-error) or on success link_id (Please not the return-value of $id1)
|
|
||||||
*/
|
|
||||||
static function link( $app1,&$id1,$app2,$id2='',$remark='',$owner=0,$lastmod=0 )
|
|
||||||
{
|
|
||||||
if (self::DEBUG)
|
|
||||||
{
|
|
||||||
echo "<p>solink.link('$app1',$id1,'$app2',$id2,'$remark',$owner)</p>\n";
|
|
||||||
}
|
|
||||||
if ($app1 == $app2 && $id1 == $id2 ||
|
|
||||||
$id1 == '' || $id2 == '' || $app1 == '' || $app2 == '')
|
|
||||||
{
|
|
||||||
return False; // dont link to self or other nosense
|
|
||||||
}
|
|
||||||
if (($link = self::get_link($app1,$id1,$app2,$id2)))
|
|
||||||
{
|
|
||||||
if ($link['link_remark'] != $remark)
|
|
||||||
{
|
|
||||||
self::update_remark($link['link_id'],$remark);
|
|
||||||
}
|
|
||||||
return $link['link_id']; // link alread exist
|
|
||||||
}
|
|
||||||
if (!$owner)
|
|
||||||
{
|
|
||||||
$owner = $GLOBALS['egw_info']['user']['account_id'];
|
|
||||||
}
|
|
||||||
return self::$db->insert(self::TABLE,array(
|
|
||||||
'link_app1' => $app1,
|
|
||||||
'link_id1' => $id1,
|
|
||||||
'link_app2' => $app2,
|
|
||||||
'link_id2' => $id2,
|
|
||||||
'link_remark' => $remark,
|
|
||||||
'link_lastmod' => $lastmod ? $lastmod : time(),
|
|
||||||
'link_owner' => $owner,
|
|
||||||
),False,__LINE__,__FILE__) ? self::$db->get_last_insert_id(self::TABLE,'link_id') : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update the remark of a link
|
|
||||||
*
|
|
||||||
* @param int $link_id link to update
|
|
||||||
* @param string $remark new text for the remark
|
|
||||||
* @return boolean true on success, else false
|
|
||||||
*/
|
|
||||||
static function update_remark($link_id,$remark)
|
|
||||||
{
|
|
||||||
return self::$db->update(self::TABLE,array(
|
|
||||||
'link_remark' => $remark,
|
|
||||||
'link_lastmod' => time(),
|
|
||||||
),array(
|
|
||||||
'link_id' => $link_id,
|
|
||||||
),__LINE__,__FILE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns array of links to $app,$id
|
|
||||||
*
|
|
||||||
* @param string $app appname
|
|
||||||
* @param string|array $id id(s) in $app
|
|
||||||
* @param string $only_app ='' if set return only links from $only_app (eg. only addressbook-entries) or NOT from if $only_app[0]=='!'
|
|
||||||
* @param string $order ='link_lastmod DESC' defaults to newest links first
|
|
||||||
* @param boolean $deleted =false Include links that have been flagged as deleted, waiting for purge of linked record.
|
|
||||||
* @param int|array $limit =null number of entries to return, default null = all or array(offset, num_rows) to return num_rows starting from offset
|
|
||||||
* @return array id => links pairs if $id is an array or just the links (only_app: ids) or empty array if no matching links found
|
|
||||||
*/
|
|
||||||
static function get_links($app, $id, $only_app='', $order='link_lastmod DESC', $deleted=false, $limit=null)
|
|
||||||
{
|
|
||||||
if (self::DEBUG)
|
|
||||||
{
|
|
||||||
echo "<p>solink.get_links($app,".print_r($id,true).",$only_app,$order,$deleted)</p>\n";
|
|
||||||
}
|
|
||||||
if (($not_only = $only_app[0] == '!'))
|
|
||||||
{
|
|
||||||
$only_app = substr($only_app,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$offset = false;
|
|
||||||
if (is_array($limit))
|
|
||||||
{
|
|
||||||
list($offset, $limit) = $limit;
|
|
||||||
}
|
|
||||||
elseif($limit)
|
|
||||||
{
|
|
||||||
$offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$links = array();
|
|
||||||
try {
|
|
||||||
foreach(self::$db->select(self::TABLE, '*', self::$db->expression(self::TABLE, '((', array(
|
|
||||||
'link_app1' => $app,
|
|
||||||
'link_id1' => $id,
|
|
||||||
),') OR (',array(
|
|
||||||
'link_app2' => $app,
|
|
||||||
'link_id2' => $id,
|
|
||||||
),'))',
|
|
||||||
$deleted ? '' : ' AND deleted IS NULL'
|
|
||||||
), __LINE__, __FILE__, $offset, $order ? " ORDER BY $order" : '', 'phpgwapi', $limit) as $row)
|
|
||||||
{
|
|
||||||
// check if left side (1) is one of our targets --> add it
|
|
||||||
if ($row['link_app1'] == $app && in_array($row['link_id1'],(array)$id))
|
|
||||||
{
|
|
||||||
self::_add2links($row,true,$only_app,$not_only,$links);
|
|
||||||
}
|
|
||||||
// check if right side (2) is one of our targets --> add it (both can be true for multiple targets!)
|
|
||||||
if ($row['link_app2'] == $app && in_array($row['link_id2'],(array)$id))
|
|
||||||
{
|
|
||||||
self::_add2links($row,false,$only_app,$not_only,$links);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if query returns exactly limit rows, we assume there are more and therefore set self::$limit_exceeded
|
|
||||||
self::$limit_exceeded = $offset !== false && count(is_array($id) ? $links : $links[$id]) == $limit;
|
|
||||||
}
|
|
||||||
// catch Illegal mix of collations (ascii_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' (1267)
|
|
||||||
// caused by non-ascii chars compared with ascii field uid
|
|
||||||
catch(egw_exception_db $e) {
|
|
||||||
_egw_log_exception($e);
|
|
||||||
}
|
|
||||||
return is_array($id) ? $links : ($links[$id] ? $links[$id] : array());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function _add2links($row,$left,$only_app,$not_only,array &$links)
|
|
||||||
{
|
|
||||||
$linked_app = $left ? $row['link_app2'] : $row['link_app1'];
|
|
||||||
$linked_id = $left ? $row['link_id2'] : $row['link_id1'];
|
|
||||||
$app_id = $left ? $row['link_id1'] : $row['link_id2'];
|
|
||||||
list($app) = explode('-',$linked_app);
|
|
||||||
if ($only_app && $not_only == ($linked_app == $only_app) || !$GLOBALS['egw_info']['user']['apps'][$app])
|
|
||||||
{
|
|
||||||
#echo "$linked_app == $only_app, ";var_dump($linked_app == $only_app);echo " ->dont return a link<br>";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#echo "returning ".(($only_app && !$not_only) ? " linkid:".$linked_id : " full array with linkid $linked_id")."<br>";
|
|
||||||
$links[$app_id][$row['link_id']] = ($only_app && !$not_only) ? $linked_id : array(
|
|
||||||
'app' => $linked_app,
|
|
||||||
'id' => $linked_id,
|
|
||||||
'remark' => $row['link_remark'],
|
|
||||||
'owner' => $row['link_owner'],
|
|
||||||
'lastmod' => $row['link_lastmod'],
|
|
||||||
'link_id' => $row['link_id'],
|
|
||||||
'deleted' => $row['deleted'],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns data of a link
|
|
||||||
*
|
|
||||||
* @param ing/string $app_link_id > 0 link_id of link or app-name of link
|
|
||||||
* @param string $id ='' id in $app, if no integer link_id given in $app_link_id
|
|
||||||
* @param string $app2 ='' appname of 2. endpoint of the link, if no integer link_id given in $app_link_id
|
|
||||||
* @param string $id2 ='' id in $app2, if no integer link_id given in $app_link_id
|
|
||||||
* @return array with link-data or False
|
|
||||||
*/
|
|
||||||
static function get_link($app_link_id,$id='',$app2='',$id2='')
|
|
||||||
{
|
|
||||||
if (self::DEBUG)
|
|
||||||
{
|
|
||||||
echo "<p>solink.get_link('$app_link_id',$id,'$app2','$id2')</p>\n";
|
|
||||||
}
|
|
||||||
if ((int) $app_link_id > 0)
|
|
||||||
{
|
|
||||||
$where = array('link_id' => $app_link_id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ($app_link_id == '' || $id == '' || $app2 == '' || $id2 == '')
|
|
||||||
{
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
$where = self::$db->expression(self::TABLE,'(',array(
|
|
||||||
'link_app1' => $app_link_id,
|
|
||||||
'link_id1' => $id,
|
|
||||||
'link_app2' => $app2,
|
|
||||||
'link_id2' => $id2,
|
|
||||||
),') OR (',array(
|
|
||||||
'link_app2' => $app_link_id,
|
|
||||||
'link_id2' => $id,
|
|
||||||
'link_app1' => $app2,
|
|
||||||
'link_id1' => $id2,
|
|
||||||
),')');
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return self::$db->select(self::TABLE,'*',$where,__LINE__,__FILE__)->fetch(ADODB_FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
// catch Illegal mix of collations (ascii_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' (1267)
|
|
||||||
// caused by non-ascii chars compared with ascii field uid
|
|
||||||
catch(egw_exception_db $e) {
|
|
||||||
_egw_log_exception($e);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove link with $link_id or all links matching given params
|
|
||||||
*
|
|
||||||
* @param $link_id link-id to remove if > 0
|
|
||||||
* @param string $app ='' app-name of links to remove
|
|
||||||
* @param string $id ='' id in $app or '' remove all links from $app
|
|
||||||
* @param int $owner =0 account_id to delete all links of a given owner, or 0
|
|
||||||
* @param string $app2 ='' appname of 2. endpoint of the link
|
|
||||||
* @param string $id2 ='' id in $app2
|
|
||||||
* @param boolean $hold_for_purge Don't really delete the link, just mark it as deleted and wait for final delete of linked entry
|
|
||||||
* @return array with deleted links
|
|
||||||
*/
|
|
||||||
static function unlink($link_id,$app='',$id='',$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
|
||||||
{
|
|
||||||
if (self::DEBUG)
|
|
||||||
{
|
|
||||||
echo "<p>solink.unlink($link_id,$app,$id,$owner,$app2,$id2)</p>\n";
|
|
||||||
}
|
|
||||||
if ((int)$link_id > 0)
|
|
||||||
{
|
|
||||||
$where = array('link_id' => $link_id);
|
|
||||||
}
|
|
||||||
elseif ($app == '' AND $owner == '')
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ($app != '' && $app2 == '')
|
|
||||||
{
|
|
||||||
$check1 = array('link_app1' => $app);
|
|
||||||
$check2 = array('link_app2' => $app);
|
|
||||||
if ($id != '')
|
|
||||||
{
|
|
||||||
$check1['link_id1'] = $id;
|
|
||||||
$check2['link_id2'] = $id;
|
|
||||||
}
|
|
||||||
$where = self::$db->expression(self::TABLE,'((',$check1,') OR (',$check2,'))');
|
|
||||||
}
|
|
||||||
elseif ($app != '' && $app2 != '')
|
|
||||||
{
|
|
||||||
$where = self::$db->expression(self::TABLE,'(',array(
|
|
||||||
'link_app1' => $app,
|
|
||||||
'link_id1' => $id,
|
|
||||||
'link_app2' => $app2,
|
|
||||||
'link_id2' => $id2,
|
|
||||||
),') OR (',array(
|
|
||||||
'link_app1' => $app2,
|
|
||||||
'link_id1' => $id2,
|
|
||||||
'link_app2' => $app,
|
|
||||||
'link_id2' => $id,
|
|
||||||
),')');
|
|
||||||
}
|
|
||||||
if ($owner)
|
|
||||||
{
|
|
||||||
if ($app) $where = array($where);
|
|
||||||
$where['link_owner'] = $owner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$deleted = array();
|
|
||||||
try {
|
|
||||||
foreach(self::$db->select(self::TABLE,'*',$where,__LINE__,__FILE__) as $row)
|
|
||||||
{
|
|
||||||
$deleted[] = $row;
|
|
||||||
}
|
|
||||||
if($hold_for_purge)
|
|
||||||
{
|
|
||||||
self::$db->update(self::TABLE,array(
|
|
||||||
'deleted' => time(),
|
|
||||||
'link_lastmod' => time(),
|
|
||||||
), $where, __LINE__,__FILE__);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self::$db->delete(self::TABLE,$where,__LINE__,__FILE__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// catch Illegal mix of collations (ascii_general_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' (1267)
|
|
||||||
// caused by non-ascii chars compared with ascii field uid
|
|
||||||
catch(egw_exception_db $e) {
|
|
||||||
_egw_log_exception($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restore links being held as deleted waiting for purge of linked record (un-delete)
|
|
||||||
*
|
|
||||||
* @param string $app ='' app-name of links to remove
|
|
||||||
* @param string $id ='' id in $app or '' remove all links from $app
|
|
||||||
*/
|
|
||||||
static function restore($app, $id)
|
|
||||||
{
|
|
||||||
if (self::DEBUG)
|
|
||||||
{
|
|
||||||
echo "<p>solink.restore($app,$id)</p>\n";
|
|
||||||
}
|
|
||||||
if ($app == '')
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$check1 = array('link_app1' => $app);
|
|
||||||
$check2 = array('link_app2' => $app);
|
|
||||||
if ($id != '')
|
|
||||||
{
|
|
||||||
$check1['link_id1'] = $id;
|
|
||||||
$check2['link_id2'] = $id;
|
|
||||||
}
|
|
||||||
$where = self::$db->expression(self::TABLE,'((',$check1,') OR (',$check2,'))');
|
|
||||||
self::$db->update(self::TABLE,array('deleted'=> null), $where, __LINE__,__FILE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes ownership of all links from $owner to $new_owner
|
|
||||||
*
|
|
||||||
* This is needed when a user/account gets deleted
|
|
||||||
* Does NOT change the modification-time
|
|
||||||
*
|
|
||||||
* @param int $owner acount_id of owner to change
|
|
||||||
* @param int $new_owner account_id of new owner
|
|
||||||
* @return int number of links changed
|
|
||||||
*/
|
|
||||||
static function chown($owner,$new_owner)
|
|
||||||
{
|
|
||||||
if ((int)$owner <= 0 || (int) $new_owner <= 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
self::$db->update(self::TABLE,array('owner'=>$new_owner),array('owner'=>$owner),__LINE__,__FILE__);
|
|
||||||
|
|
||||||
return self::$db->affected_rows();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all links from a given app's entries to an other app's entries, which both link to the same 3. app and id
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* I search all timesheet's linked to a given project and id(s), who are also linked to other entries,
|
|
||||||
* which link to the same project:
|
|
||||||
*
|
|
||||||
* ($app='timesheet'/some id) <--a--> (other app/other id) <--b--> ($t_app='projectmanager'/$t_id=$pm_id)
|
|
||||||
* ^ ^
|
|
||||||
* +---------------------------c-----------------------------------------+
|
|
||||||
*
|
|
||||||
* egw_link::get_3links('timesheet','projectmanager',$pm_id) returns the links (c) between the timesheet and the project,
|
|
||||||
* plus the other app/id in the keys 'app3' and 'id3'
|
|
||||||
*
|
|
||||||
* @param string $app app the returned links are linked on one side (atm. this must be link_app1!)
|
|
||||||
* @param string $target_app app the returned links other side link also to
|
|
||||||
* @param string|array $target_id =null id(s) the returned links other side link also to
|
|
||||||
* @param boolean $just_app_ids =false return array with link_id => app_id pairs, not the full link record
|
|
||||||
* @param string $order ='link_lastmod DESC' defaults to newest links first
|
|
||||||
* @param int|array $limit =null number of entries to return, default null = all or array(offset, num_rows) to return num_rows starting from offset
|
|
||||||
* @return array with links from entries from $app to $target_app/$target_id plus the other (b) link_id/app/id in the keys 'link3'/'app3'/'id3'
|
|
||||||
*/
|
|
||||||
static function get_3links($app, $target_app, $target_id=null, $just_app_ids=false, $order='link_lastmod DESC', $limit=null)
|
|
||||||
{
|
|
||||||
$table = self::TABLE;
|
|
||||||
$arrayofselects=array(
|
|
||||||
// retrieve the type of links, where the relation is realized as timesheet->infolog/tracker via infolog->projectmanager to timesheet->projectmanager
|
|
||||||
array('table'=>self::TABLE,
|
|
||||||
'cols'=>'c.*,b.link_app1 AS app3,b.link_id1 AS id3,b.link_id AS link3',
|
|
||||||
'where'=>'a.link_app1='.self::$db->quote($app).' AND c.link_app2='.self::$db->quote($target_app).
|
|
||||||
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND c.',array('link_id2' => $target_id))),
|
|
||||||
'join'=>" a
|
|
||||||
JOIN $table b ON a.link_id2=b.link_id1 AND a.link_app2=b.link_app1
|
|
||||||
JOIN $table c ON a.link_id1=c.link_id1 AND a.link_app1=c.link_app1 AND a.link_id!=c.link_id AND c.link_app2=b.link_app2 AND c.link_id2=b.link_id2",
|
|
||||||
),
|
|
||||||
// retrieve the type of links, where the relation is realized as timesheet->infolog/tracker and projectmanager->timesheet
|
|
||||||
array('table'=>self::TABLE,
|
|
||||||
'cols'=>'b.link_id, b.link_app2 as app1, b.link_id2 as id1, b.link_app1 as app2, b.link_id1 as id2, b.link_remark,b.link_lastmod,b.link_owner,b.deleted,c.link_app1 AS app3,c.link_id1 AS id3,c.link_id AS link3',
|
|
||||||
'where'=>'a.link_app1='.self::$db->quote($app).' AND b.link_app1='.self::$db->quote($target_app).
|
|
||||||
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND b.',array('link_id1' => $target_id))),
|
|
||||||
'join'=>" a
|
|
||||||
JOIN $table b ON a.link_id1=b.link_id2 AND a.link_app1=b.link_app2
|
|
||||||
JOIN $table c ON a.link_id2=c.link_id1 AND a.link_app2=c.link_app1 AND a.link_id!=c.link_id AND c.link_app2=b.link_app1 AND c.link_id2=b.link_id1",
|
|
||||||
),
|
|
||||||
// retrieve the type of links, where the relation is realized as timesheet->projectmanager and infolog->timesheet
|
|
||||||
array('table'=>self::TABLE,
|
|
||||||
'cols'=>'a.*,c.link_app1 AS app3,c.link_id1 AS id3,c.link_id AS link3',
|
|
||||||
'where'=>'a.link_app1='.self::$db->quote($app).' AND a.link_app2='.self::$db->quote($target_app).
|
|
||||||
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND a.',array('link_id2' => $target_id))),
|
|
||||||
'join'=>" a
|
|
||||||
JOIN $table b ON a.link_id1=b.link_id2 AND a.link_app1=b.link_app2
|
|
||||||
JOIN $table c ON a.link_id2=c.link_id2 AND a.link_app2=c.link_app2 AND a.link_id!=c.link_id AND c.link_app1=b.link_app1 AND c.link_id1=b.link_id1",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
$offset = false;
|
|
||||||
if (is_array($limit))
|
|
||||||
{
|
|
||||||
list($offset, $limit) = $limit;
|
|
||||||
}
|
|
||||||
elseif($limit)
|
|
||||||
{
|
|
||||||
$offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$links = array();
|
|
||||||
foreach(self::$db->union($arrayofselects, __LINE__, __FILE__, $order, $offset, $limit) as $row)
|
|
||||||
{
|
|
||||||
if ($just_app_ids)
|
|
||||||
{
|
|
||||||
if ($row['link_app1'] == $target_app && (is_null($target_id) || in_array($row['link_id1'],(array)$target_id)))
|
|
||||||
{
|
|
||||||
$links[$row['link_id']] = $row['link_id2'];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$links[$row['link_id']] = $row['link_id1'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$links[] = egw_db::strip_array_keys($row,'link_');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if query returns exactly limit rows, we assume there are more and therefore set self::$limit_exceeded
|
|
||||||
self::$limit_exceeded = $offset !== false && count($links) == $limit;
|
|
||||||
|
|
||||||
return $links;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise our static vars
|
|
||||||
*/
|
|
||||||
static function init_static( )
|
|
||||||
{
|
|
||||||
self::$db = $GLOBALS['egw']->db;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
solink::init_static();
|
|
||||||
|
Loading…
Reference in New Issue
Block a user