egroupware_official/filemanager/inc/class.filemanager_collab.inc.php
Hadi Nategh 6d80f6c351 W.I.P. collab editor:
- Implement discard changes action
2016-08-22 17:47:00 +02:00

285 lines
6.9 KiB
PHP

<?php
/**
* EGroupware - Filemanager Collab
*
* @link http://www.egroupware.org
* @package filemanager
* @author Hadi Nategh <hn-AT-stylite.de>
* @copyright (c) 2016 by Stylite AG
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
use EGroupware\Api;
class filemanager_collab extends filemanager_collab_bo {
/**
* Methods callable via menuaction
*
* @var array
*/
var $public_functions = array(
'poll' => true
);
/**
* Constructor
*
*/
function __construct()
{
parent::__construct();
}
/**
* Join session, initialises edit session for opened file by user
*
* @param type $es_id session id
* @return array returns an array consists of session data
*/
function join_session ($es_id)
{
$response = $this->initSession($es_id);
$response += array (
'id' => $GLOBALS['egw_info']['user']['account_id'],
'full_name' => $GLOBALS['egw_info']['user']['account_fullname'],
'success' => true
);
return $response;
}
/**
* This function gets called when user leaves the session
*
* @param string $es_id
* @param string $member_id
*
* @return array returns an array of data as response for client-side
*/
function leave_session ($es_id, $member_id)
{
if (!$this->is_sessionValid($es_id) || !$this->is_memberValid($es_id, $member_id)) throw new Exception ('Session is not valid!');
return array (
'session_id' => $es_id,
'memberid' => $member_id,
'success' => $this->OP_removeMember($es_id, $member_id)
);
}
/**
* Polling mechanisim to sysncronise data
*
* @throws Exception
*/
function poll ()
{
// Get POST request payload
$payload = file_get_contents('php://input');
$params = $payload? json_decode ($payload, true): null;
$response = array();
if (is_array($params))
{
switch ($params['command'])
{
case 'join_session':
$response = $this->join_session($params['args']['es_id'],$params['args']['user_id']);
break;
case 'leave_session':
$response = $this->leave_session($params['args']['es_id'],$params['args']['member_id']);
break;
case 'sync_ops':
try
{
$memberid = $params['args']['member_id']? $params['args']['member_id']: '';
$es_id = $params['args']['es_id'];
$seq_head = (string) isset($params['args']['seq_head'])? $params['args']['seq_head']: null;
// we need to inform clients about session changes to update themselves
// based on that. For instance, after discarding changes other participants
// should get notified to reload their session.
if (!$this->is_memberValid($es_id, $memberid)) {
$response = array (
'result' => 'error',
'error' => 'ENOSESSION'
);
throw new Exception('Session is not valid!');
}
if(!is_null($seq_head))
{
$client_ops = $params['args']['client_ops']? $params['args']['client_ops']: [];
$current_seq_head = $this->OP_getHeadSeq($es_id);
if ($seq_head == $current_seq_head) {
if (count($client_ops)>0)
{
$newHead = $this->get_newHead($es_id, $memberid, $client_ops);
$response = array(
'result' => 'added',
'head_seq' => $newHead ? $newHead : $current_seq_head
);
}
else
{
$response = array(
'result' => 'new_ops',
'ops' => array(),
'head_seq' => $current_seq_head
);
}
}
else
{
$response = array(
'result' => count($client_ops)>0 ? 'conflict' : 'new_ops',
'ops' => $this->OP_getOPSECS($es_id, $seq_head),
'head_seq' => $current_seq_head,
);
}
}
else
{
throw new Exception('Invalid seq head!');
}
} catch (Exception $ex) {
error_log($ex->getMessage());
}
break;
default:
//
}
}
header('content-type: application/json; charset=utf-8');
echo json_encode($response);
exit();
}
/**
* Function to get a new head sequence
*
* @param string $es_id session id
* @param string $member_id member id
* @param array $client_ops opspec from client side
*
* @return string return a seq head number
*/
function get_newHead ($es_id, $member_id, $client_ops)
{
$this->OP_addOPS($es_id, $member_id, $client_ops);
return $this->OP_getHeadSeq($es_id);
}
/**
* Ajax function to handle actions called by client-side
* types: save, delete, discard
*
* @param type $es_id
* @param type $action
*/
function ajax_actions ($es_id, $action)
{
switch ($action)
{
case 'save':
$this->SESSION_Save($es_id);
break;
case 'delete':
$this->SESSION_cleanup($es_id);
break;
case 'discard':
$this->OP_Discard($es_id);
break;
default:
//
}
}
/**
* Check if the collaboration is allowed for given file path
*
* @param string $file_path file path
* @param int $_right VFS file access right
*
* @return boolean returns true if allowed
*/
function is_collabAllowed ($file_path, $_right=null)
{
$paths = explode('/webdav.php', $file_path);
$right = $_right ? $_right : Api\Vfs::WRITABLE;
$allowed = Api\Vfs::check_access($paths[1], $right) &&
!preg_match('/\/api\/js\/webodf\/template.odf$/', $file_path);
return $allowed;
}
/**
* Check if session is valid
*
* @param type $es_id
*
* @return boolean return true if session is valid otherwise false
*/
function is_sessionValid ($es_id)
{
$session = $this->SESSION_Get($es_id);
return $session? true : false;
}
/**
* Check if the member id of the session has valid status
* status: 1 is valid 0 is invalid
*
* @param type $es_id
* @param type $member_id
* @return boolean returns true if it's valid
*/
function is_memberValid ($es_id, $member_id)
{
$member = $this->MEMBER_getMember($es_id, $member_id);
return $member && $member['status'] != 0 ? true: false;
}
/**
* Function to get genesis url by generating a temp genesis temp file
* out of given path, and returnig es_id md5 hash and genesis url to
* client.
*
* @param type $file_path file path
*
*/
function ajax_getGenesisUrl ($file_path)
{
$result = array();
$es_id = md5($file_path);
$paths = explode('/webdav.php', $file_path);
$dir_parts = explode('/',$paths[1]);
array_pop($dir_parts);
$dir = join('/', $dir_parts);
$response = Api\Json\Response::get();
$session = $this->SESSION_Get($es_id);
if ($session && $session['genesis_url'] !== '')
{
$result = array (
'es_id' => $session['es_id'],
'genesis_url' => $session['genesis_url']
);
}
else if ($this->is_collabAllowed($file_path, Api\Vfs::WRITABLE))
{
$genesis_file = $dir.'/.'.$es_id.'.webodf.odt';
$genesis_url = $paths[0].'/webdav.php'.$genesis_file;
$result = array (
'es_id' => $es_id,
'genesis_url' => $genesis_url
);
Api\Vfs::copy($paths[1], $genesis_file);
$this->SESSION_add2Db($es_id, $genesis_url);
}
$response->data($result);
}
}