Migrate to simple orm

pull/1/head
Victor Dubiniuk 11 years ago
parent 6e7818a967
commit 7b858e75b5

@ -30,20 +30,21 @@ class DocumentController extends Controller{
/**
* Process partial/complete file download
* @param array $args - array containing session id as anelement with a key es_id
* @param array $args - array containing session id as an element with a key es_id
*/
public static function serve($args){
$session = Session::getSession(@$args['es_id']);
$file = new File(@$session['file_id']);
$session = new Db_Session();
$sessionData = $session->load(@$args['es_id'])->getData();
$file = new File(@$sessionData['file_id']);
if (!$file->isPublicShare()){
self::preDispatch(false);
} else {
self::preDispatchGuest(false);
}
$filename = isset($session['genesis_url']) ? $session['genesis_url'] : '';
$documentsView = new View('/' . $session['owner']);
$filename = isset($sessionData['genesis_url']) ? $sessionData['genesis_url'] : '';
$documentsView = new View('/' . $sessionData['owner']);
$download = new Download($documentsView->initDocumentsView(), $filename);
$download->sendResponse();
}
@ -66,11 +67,13 @@ class DocumentController extends Controller{
$fileIds[] = $document['fileid'];
}
$sessions = Session::getSessionsByFileIds($fileIds);
$session = new Db_Session();
$sessions = $session->getCollectionBy('file_id', $fileIds);
$members = array();
$member = new Db_Member();
foreach ($sessions as $session) {
$members[$session['es_id']] = Member::getMembersByEsId($session['es_id']);
$members[$session['es_id']] = $member->getCollectionBy('es_id', $session['es_id']);
}
\OCP\JSON::success(array('documents' => $documents,'sessions' => $sessions,'members' => $members));

@ -43,8 +43,9 @@ try{
$request = new Request();
$esId = $request->getParam('args/es_id');
$session = Session::getSession($esId);
$file = new File(@$session['file_id']);
$session = new Db_Session();
$sessionData = $session->load($esId)->getData();
$file = new File(@$sessionData['file_id']);
if (!$file->isPublicShare()){
Controller::preDispatch(false);
} else {
@ -55,7 +56,10 @@ try{
switch ($command){
case 'query_memberdata_list':
$ids = $request->getParam('args/member_ids');
$members = Member::getMembersAsArray($ids);
$member = new Db_Member();
$members = $member->getCollectionBy('member_id', $ids);
$response["memberdata_list"] = array_map(
function($x){
$x['display_name'] = \OCP\User::getDisplayName($x['uid']);
@ -91,11 +95,13 @@ try{
$ops = $request->getParam('args/client_ops');
$hasOps = is_array($ops) && count($ops)>0;
$currentHead = Op::getHeadSeq($esId);
$op = new Db_Op();
$currentHead = $op->getHeadSeq($esId);
$member = new Db_Member();
try {
Member::updateMemberActivity($memberId);
$member->updateActivity($memberId);
} catch (\Exception $e){
}
// TODO handle the case ($currentHead == "") && ($seqHead != "")
@ -104,7 +110,7 @@ try{
if ($hasOps) {
// incoming ops without conflict
// Add incoming ops, respond with a new head
$newHead = Op::addOpsArray($esId, $memberId, $ops);
$newHead = Db_Op::addOpsArray($esId, $memberId, $ops);
$response["result"] = 'added';
$response["head_seq"] = $newHead ? $newHead : $currentHead;
} else {
@ -114,18 +120,16 @@ try{
$response["head_seq"] = $currentHead;
}
} else { // HEADs do not match
$response["ops"] = Op::getOpsAfterJson($esId, $seqHead);
$response["ops"] = $op->getOpsAfterJson($esId, $seqHead);
$response["head_seq"] = $currentHead;
$response["result"] = $hasOps ? 'conflict' : 'new_ops';
}
$inactiveMembers = Member::cleanSession($esId);
if (is_array($inactiveMembers)){
foreach ($inactiveMembers as $member){
Op::removeCursor($esId, $member['member_id']);
}
$inactiveMembers = $member->updateByTimeout($esId);
foreach ($inactiveMembers as $inactive){
$op->removeCursor($esId, $inactive['member_id']);
}
} else {
// Error - no seq_head passed
throw new BadRequestException();

@ -30,7 +30,7 @@ class SessionController extends Controller{
protected static function join($uid, $file){
try{
$session = Session::start($uid, $file);
$session = Db_Session::start($uid, $file);
\OCP\JSON::success($session);
exit();
} catch (\Exception $e){
@ -45,8 +45,8 @@ class SessionController extends Controller{
*/
public static function save(){
try {
$sessionID = @$_SERVER['HTTP_WEBODF_SESSION_ID'];
if (!$sessionID){
$esId = @$_SERVER['HTTP_WEBODF_SESSION_ID'];
if (!$esId){
throw new \Exception('Session id can not be empty');
}
@ -58,12 +58,14 @@ class SessionController extends Controller{
throw new \Exception('New conent missing');
}
$session = Session::getSession($sessionID);
if (!$session){
$session = new Db_Session();
$session->load($esId);
if (!$session->hasData()){
throw new \Exception('Session does not exist');
}
$file = new File($session['file_id']);
$sessionData = $session->getData();
$file = new File($sessionData['file_id']);
if (!$file->isPublicShare()){
self::preDispatch();
} else {
@ -80,7 +82,7 @@ class SessionController extends Controller{
if ($view->file_exists($path)){
$currentHash = sha1($view->file_get_contents($path));
if ($currentHash !== $session['genesis_hash']){
if ($currentHash !== $sessionData['genesis_hash']){
// Original file was modified externally. Save to a new one
$path = Helper::getNewFileName($view, $path, '-conflict');
}
@ -88,7 +90,7 @@ class SessionController extends Controller{
if ($view->file_put_contents($path, $content)){
//Document saved successfully. Cleaning session data
Session::cleanUp($sessionID);
Db_Session::cleanUp($esId);
}
\OCP\JSON::success();
exit();
@ -105,7 +107,8 @@ class SessionController extends Controller{
$info = array();
if (is_array($items)){
$info = Session::getInfoByFileid($items);
$session = new Db_Session();
$info = $session->getInfoByFileId($items);
}
\OCP\JSON::success(array(
@ -115,10 +118,8 @@ class SessionController extends Controller{
public static function listAll(){
self::preDispatch();
$sessions = Session::getAll();
if (!is_array($sessions)){
$sessions = array();
}
$session = new Db_Session();
$sessions = $session->getCollection();
$preparedSessions = array_map(
function($x){
@ -132,10 +133,8 @@ class SessionController extends Controller{
public static function listAllHtml(){
self::preDispatch();
$sessions = Session::getAll();
if (!is_array($sessions)){
$sessions = array();
}
$session = new Db_Session();
$sessions = $session->getCollection();
$preparedSessions = array_map(
function($x){

@ -40,6 +40,9 @@ OC::$CLASSPATH['OCA\Documents\SessionController'] = 'documents/ajax/sessionContr
OC::$CLASSPATH['OCA\Documents\UserController'] = 'documents/ajax/userController.php';
OC::$CLASSPATH['OCA\Documents\Download_Simple'] = 'documents/lib/download/simple.php';
OC::$CLASSPATH['OCA\Documents\Download_Range'] = 'documents/lib/download/range.php';
OC::$CLASSPATH['OCA\Documents\Db_Session'] = 'documents/lib/db/session.php';
OC::$CLASSPATH['OCA\Documents\Db_Member'] = 'documents/lib/db/member.php';
OC::$CLASSPATH['OCA\Documents\Db_Op'] = 'documents/lib/db/op.php';
//Listen to delete file signal
\OCP\Util::connectHook('OC_Filesystem', 'delete', "OCA\Documents\Storage", "onDelete");

@ -15,16 +15,189 @@ namespace OCA\Documents;
* Generic DB class
*/
class Db {
abstract class Db {
protected $data;
protected $tableName;
protected $insertStatement;
protected $loadStatement;
public function __construct($data = array()){
$this->setData($data);
}
/**
* Insert current object data into database
* @return mixed
*/
public function insert(){
$result = $this->execute($this->insertStatement);
return $result;
}
/**
* Get id of the recently inserted record
* @return mixed
*/
public function getLastInsertId(){
return \OCP\DB::insertid($this->tableName);
}
/**
* Get single record by primary key
* @param type $value primary key value
* @return \OCA\Documents\Db
*/
public function load($value){
if (!is_array($value)){
$value = array($value);
}
$result = $this->execute($this->loadStatement, $value);
$data = $result->fetchRow();
if (!is_array($data)){
$data = array();
}
$this->data = $data;
return $this;
}
/**
* Get single record matching condition
* @param string $field for WHERE condition
* @param mixed $value matching value(s)
* @return \OCA\Documents\Db
* @throws Exception
*/
public function loadBy($field, $value){
if (!is_array($value)){
$value = array($value);
}
$result = $this->execute('SELECT * FROM ' . $this->tableName . ' WHERE `'. $field .'` =?', $value);
$data = $result->fetchAll();
if (!is_array($data) || !count($data)){
$this->data = array();
} elseif (count($data)!=1) {
throw new Exception('Duplicate ' . $value . ' for the filed ' . $field);
} else {
$this->data = $data[0];
}
return $this;
}
/**
* Delete records matching the condition
* @param string $field for WHERE condition
* @param mixed $value matching value(s)
*/
public function deleteBy($field, $value){
if (!is_array($value)){
$value = array($value);
}
if (count($value)===1){
$result = $this->execute('DELETE FROM ' . $this->tableName . ' WHERE `'. $field .'` =?', $value);
} else {
$stmt = $this->buildInQuery($field, $value);
$result = $this->execute('DELETE FROM ' . $this->tableName . ' WHERE ' . $stmt, $value);
}
}
/**
* Get all records from the table
* @return array
*/
public function getCollection(){
$result = $this->execute('SELECT * FROM ' . $this->tableName);
$data = $result->fetchAll();
if (!is_array($data)){
$data = array();
}
return $data;
}
/**
* Get array of matching records
* @param string $field for WHERE condition
* @param mixed $value matching value(s)
* @return array
*/
public function getCollectionBy($field, $value){
if (!is_array($value)){
$value = array($value);
}
if (count($value)===1){
$result = $this->execute('SELECT * FROM ' . $this->tableName . ' WHERE `'. $field .'` =?', $value);
} else {
$stmt = $this->buildInQuery($field, $value);
$result = $this->execute('SELECT * FROM ' . $this->tableName . ' WHERE '. $stmt , $value);
}
$data = $result->fetchAll();
if (!is_array($data)){
$data = array();
}
return $data;
}
/**
* Get object data
* @return Array
*/
public function getData(){
return $this->data;
}
/**
* Set object data
* @param array $data
*/
public function setData($data){
$this->data = $data;
}
/**
* Check if there are any data in current object
* @return bool
*/
public function hasData(){
return count($this->data)>0;
}
/**
* Build placeholders for the query with variable input data
* @param string $field field name
* @param Array $array data
* @return String string of '?' placeholders matching the number of elements in array
* @return String `field` IN (?, ?...) placeholders matching the number of elements in array
*/
public static function buildPlaceholders($array){
protected function buildInQuery($field, $array){
$count = count($array);
$placeholders = array_fill(0, $count, '?');
$stmt = implode(', ', $placeholders);
return $stmt;
return '`' . $field . '` IN (' . $stmt . ')';
}
/**
* Execute a query on database
* @param string $statement query to be executed
* @param mixed $args value(s) for the query.
* If omited the query will be run on the current object $data
* @return mixed (array/false)
*/
protected function execute($statement, $args = null){
$query = \OCP\DB::prepare($statement);
if (!is_null($args)){
$result = $query->execute($args);
} elseif (count($this->data)){
$result = $query->execute($this->data);
} else {
$result = $query->execute();
}
return $result;
}
}
}

@ -0,0 +1,97 @@
<?php
/**
* ownCloud - Documents App
*
* @author Victor Dubiniuk
* @copyright 2013 Victor Dubiniuk victor.dubiniuk@gmail.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Documents;
class Db_Member extends Db{
const DB_TABLE = '`*PREFIX*documents_member`';
const ACTIVITY_THRESHOLD = 60; // 1 Minute
const MEMBER_STATUS_ACTIVE = 1;
const MEMBER_STATUS_INACTIVE = 2;
protected $tableName = '`*PREFIX*documents_member`';
protected $insertStatement = 'INSERT INTO `*PREFIX*documents_member` (`es_id`, `uid`, `color`, `last_activity`)
VALUES (?, ?, ?, ?)';
protected $loadStatement = 'SELECT * FROM `*PREFIX*documents_member` WHERE `member_id`= ?';
public function updateActivity($memberId){
return $this->execute(
'UPDATE ' . $this->tableName . ' SET `last_activity`=?, `status`=? WHERE `member_id`=?',
array(
time(),
self::MEMBER_STATUS_ACTIVE,
$memberId
)
);
}
/**
* Mark members as inactive
* @param string $esId - session Id
* @return array - list of memberId that were marked as inactive
*/
public function updateByTimeout($esId){
$time = $this->getInactivityPeriod();
$result = $this->execute('
SELECT `member_id`
FROM ' . self::DB_TABLE . '
WHERE `es_id`= ?
AND `last_activity`<?
AND `status`=?
',
array(
$esId,
$time,
self::MEMBER_STATUS_ACTIVE
)
);
$deactivated = $result->fetchAll();
if (is_array($deactivated) && count($deactivated)){
$deactivated = array_map(
function($x){
return ($x['member_id']);
}, $deactivated
);
$this->deactivate($deactivated);
} else {
$deactivated = array();
}
return $deactivated;
}
/**
* Update members to inactive state
* @param array $memberIds
*/
protected function deactivate($memberIds){
$stmt = $this->buildInQuery('member_id', $memberIds);
array_unshift($memberIds, self::MEMBER_STATUS_INACTIVE);
$this->execute('
UPDATE ' . $this->tableName . '
SET `status`=?
WHERE ' . $stmt,
$memberIds
);
}
protected function getInactivityPeriod(){
return time() - self::ACTIVITY_THRESHOLD;
}
}

@ -11,40 +11,36 @@
namespace OCA\Documents;
class Op {
class Db_Op extends Db {
const DB_TABLE = '`*PREFIX*documents_op`';
public static function add($esId, $memberId, $opspec){
$query = \OCP\DB::prepare('
INSERT INTO ' . self::DB_TABLE . ' (`es_id`, `member`, `opspec`)
VALUES (?, ?, ?)
');
$query->execute(array(
$esId,
$memberId,
$opspec,
));
return \OCP\DB::insertid(self::DB_TABLE);
}
protected $tableName = '`*PREFIX*documents_op`';
protected $insertStatement = 'INSERT INTO `*PREFIX*documents_op` (`es_id`, `member`, `opspec`) VALUES (?, ?, ?)';
public static function addOpsArray($esId, $memberId, $ops){
$lastSeq = "";
$opObj = new Db_Op();
foreach ($ops as $op) {
$lastSeq = self::add($esId, $memberId, json_encode($op));
$opObj->setData(array(
$esId,
$memberId,
json_encode($op)
));
$opObj->insert();
$lastSeq = $opObj->getLastInsertId();
}
return $lastSeq;
}
/**
* @returns "" when there are no Ops, or the seq of the last Op
*/
public static function getHeadSeq($esId){
public function getHeadSeq($esId){
$query = \OCP\DB::prepare('
SELECT `seq`
FROM ' . self::DB_TABLE . '
FROM ' . $this->tableName . '
WHERE `es_id`=?
ORDER BY `seq` DESC
', 1);
@ -56,8 +52,8 @@ class Op {
return !$result ? "" : $result;
}
public static function getOpsAfterJson($esId, $seq){
$ops = self::getOpsAfter($esId, $seq);
public function getOpsAfterJson($esId, $seq){
$ops = $this->getOpsAfter($esId, $seq);
if (!is_array($ops)){
$ops = array();
}
@ -72,7 +68,7 @@ class Op {
return $ops;
}
public static function getOpsAfter($esId, $seq){
public function getOpsAfter($esId, $seq){
if ($seq == ""){
$seq = -1;
}
@ -86,18 +82,13 @@ class Op {
$result = $query->execute(array($esId, $seq));
return $result->fetchAll();
}
public static function deleteBySessionId($esId){
$query = \OCP\DB::prepare('DELETE FROM ' . self::DB_TABLE . ' WHERE `es_id` = ?');
$query->execute(array($esId));
}
public static function removeCursor($esId, $memberId){
return self::add(
$esId,
0,
'{"optype":"RemoveCursor","memberid":"'. $memberId .'","reason":"server-idle","timestamp":'. time() .'}'
);
public function removeCursor($esId, $memberId){
$op = new Db_Op(array(
$esId,
0,
'{"optype":"RemoveCursor","memberid":"'. $memberId .'","reason":"server-idle","timestamp":'. time() .'}'
));
$op->insert();
}
}

@ -0,0 +1,163 @@
<?php
/**
* ownCloud - Documents App
*
* @author Victor Dubiniuk
* @copyright 2013 Victor Dubiniuk victor.dubiniuk@gmail.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Documents;
/**
* Session management
*/
class Db_Session extends \OCA\Documents\Db {
/**
* DB table
*/
const DB_TABLE = '`*PREFIX*documents_session`';
protected $tableName = '`*PREFIX*documents_session`';
protected $insertStatement = 'INSERT INTO `*PREFIX*documents_session` (`es_id`, `genesis_url`, `genesis_hash`, `owner`, `file_id`)
VALUES (?, ?, ?, ?, ?)';
protected $loadStatement = 'SELECT * FROM `*PREFIX*documents_session` WHERE `es_id`= ?';
/**
* Start a editing session or return an existing one
* @param string $uid of the user starting a session
* @param \OCA\Documents\File $file - file object
* @return array
* @throws \Exception
*/
public static function start($uid, File $file){
list($ownerView, $path) = $file->getOwnerViewAndPath();
$oldSession = new Db_Session();
$oldSession->loadBy('file_id', $file->getFileId());
//If there is no existing session we need to start a new one
if (!$oldSession->hasData()){
//TODO: check if genesis document is a valid odt
$genesisPath = $ownerView->storeDocument($ownerView, $path);
if (!$genesisPath){
throw new \Exception('Unable to copy document. Check permissions and make sure you have enought free space.');
}
$hash = $ownerView->getHashByGenesis($genesisPath);
$newSession = new Db_Session(array(
$genesisPath, $hash, $file->getOwner(), $file->getFileId()
));
if (!$newSession->insert()){
throw new \Exception('Failed to add session into database');
}
}
$session = $oldSession
->loadBy('file_id', $file->getFileId())
->getData()
;
$member = new Db_Member(array(
$session['es_id'],
$uid,
Helper::getRandomColor()
));
if ($member->insert()){
$session['member_id'] = (string) $member->getLastInsertId();
} else {
throw new \Exception('Failed to add member into database');
}
$session['permissions'] = $ownerView->getFilePermissions($path);
return $session;
}
public static function cleanUp($esId){
$session = new Db_Session();
$session->deleteBy('es_id', $esId);
$member = new Db_Member();
$member->deleteBy('es_id', $esId);
$op= new Db_Op();
$op->deleteBy('es_id', $esId);
}
public function insert(){
$esId = $this->getUniqueSessionId();
array_unshift($this->data, $esId);
return parent::insert($this->data);
}
public function getInfo($esId){
$result = $this->execute('
SELECT `s`.*, COUNT(`m`.`member_id`) AS `users`
FROM ' . $this->tableName . ' AS `s`
LEFT JOIN `*PREFIX*documents_member` AS `m` ON `s`.`es_id`=`m`.`es_id`
AND `m`.`status`=' . Db_Member::MEMBER_STATUS_ACTIVE . '
AND `m`.`uid` != ?
WHERE `s`.`es_id` = ?
GROUP BY `m`.`es_id`
',
array(
\OCP\User::getUser(),
$esId
)
);
$info = $result->fetchRow();
if (!is_array($info)){
$info = array();
}
return $info;
}
public function getInfoByFileId($fileIds){
if (!is_array($fileIds)){
return array();
}
$stmt = $this->buildInQuery('file_id', $fileIds);
$result = $this->execute('
SELECT `s`.*, COUNT(`m`.`member_id`) AS `users`
FROM ' . $this->tableName . ' AS `s`
LEFT JOIN `*PREFIX*documents_member` AS `m` ON `s`.`es_id`=`m`.`es_id`
AND `m`.`status`=' . Db_Member::MEMBER_STATUS_ACTIVE . '
WHERE `s`.`file_id` ' . $stmt .'
GROUP BY `m`.`es_id`',
$fileIds
);
$info = $result->fetchAll();
if (!is_array($info)){
$info = array();
}
return $info;
}
protected function getUniqueSessionId(){
$testSession = new Db_Session();
do{
// this prevents branching for stable5 for now:
// OC_Util::generate_random_bytes was camelCased
if (method_exists('\OC_Util', 'generate_random_bytes')){
$id = \OC_Util::generate_random_bytes(30);
} else {
$id = \OC_Util::generateRandomBytes(30);
}
}while ($testSession->load($id)->hasData());
return $id;
}
}

@ -1,133 +0,0 @@
<?php
/**
* ownCloud - Documents App
*
* @author Victor Dubiniuk
* @copyright 2013 Victor Dubiniuk victor.dubiniuk@gmail.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Documents;
class Member extends Db{
const DB_TABLE = '`*PREFIX*documents_member`';
const ACTIVITY_THRESHOLD = 60; // 10 Minutes
const MEMBER_STATUS_ACTIVE = 1;
const MEMBER_STATUS_INACTIVE = 2;
public static function add($esId, $uid, $color){
$query = \OCP\DB::prepare('
INSERT INTO ' . self::DB_TABLE . ' (`es_id`, `uid`, `color`, `last_activity`)
VALUES (?, ?, ?, ?)
');
$query->execute(array(
$esId,
$uid,
$color,
time()
));
return \OCP\DB::insertid(self::DB_TABLE);
}
public static function getMember($id){
$query = \OCP\DB::prepare('SELECT * FROM ' . self::DB_TABLE . ' WHERE `member_id`= ?');
$result = $query->execute(array($id));
return $result->fetchRow();
}
public static function getMembersAsArray($ids){
$memberCount = count($ids);
if (!$memberCount || !is_array($ids)){
return array();
}
$stmt = self::buildPlaceholders($ids);
$query = \OCP\DB::prepare('SELECT * FROM ' . self::DB_TABLE . ' WHERE `member_id` IN (' . $stmt . ')');
$result = $query->execute($ids);
return $result->fetchAll();
}
public static function updateMemberActivity($memberId){
$query = \OCP\DB::prepare('UPDATE ' . self::DB_TABLE . ' SET `last_activity`=?, `status`=? WHERE `member_id`=?');
$query->execute(array(
time(),
self::MEMBER_STATUS_ACTIVE,
$memberId
));
}
public static function getMembersByEsId($esId, $lastActivity = null){
if (is_null($lastActivity)){
$activeSince = self::getInactivityPeriod();
} else {
$activeSince = $lastActivity;
}
$query = \OCP\DB::prepare('SELECT * FROM ' . self::DB_TABLE . ' WHERE `es_id`= ? AND `last_activity` > ?');
$result = $query->execute(array($esId, $activeSince));
return $result->fetchAll();
}
/**
* Mark memebers as inactive
* @param string $esId - session Id
* @return array - list of memberId that were marked as inactive
*/
public static function cleanSession($esId){
$time = self::getInactivityPeriod();
$query = \OCP\DB::prepare('
SELECT `member_id`
FROM ' . self::DB_TABLE . '
WHERE `es_id`= ?
AND `last_activity`<?
AND `status`=?
');
$result = $query->execute(array(
$esId,
$time,
self::MEMBER_STATUS_ACTIVE
));
$deactivated = $result->fetchAll();
self::deactivate($esId, $time);
return $deactivated;
}
/**
* Update members to inactive state
* @param string $esId
* @param timestamp $time
*/
protected static function deactivate($esId, $time){
$query = \OCP\DB::prepare('
UPDATE ' . self::DB_TABLE . '
SET `status`=?
WHERE `es_id`=?
AND `last_activity`<?
');
$query->execute(array(
self::MEMBER_STATUS_INACTIVE,
$esId,
$time
));
}
public static function deleteBySessionId($esId){
$query = \OCP\DB::prepare('DELETE FROM ' . self::DB_TABLE . ' WHERE `es_id` = ?');
$query->execute(array($esId));
}
protected static function getInactivityPeriod(){
return time() - self::ACTIVITY_THRESHOLD;
}
}

@ -1,183 +0,0 @@
<?php
/**
* ownCloud - Documents App
*
* @author Victor Dubiniuk
* @copyright 2013 Victor Dubiniuk victor.dubiniuk@gmail.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Documents;
class Session extends Db {
const DB_TABLE = '`*PREFIX*documents_session`';
public static function start($uid, File $file){
list($ownerView, $path) = $file->getOwnerViewAndPath();
$session = Session::getSessionByFileId( $file->getFileId() );
//If there is no existing session we need to start a new one
if (!$session || empty($session)){
$genesisPath = $ownerView->storeDocument($ownerView, $path);
if (!$genesisPath){
throw new \Exception('Unable to copy document. Check permissions and make sure you have enought free space.');
}
$hash = $ownerView->getHashByGenesis($genesisPath);
$session = Session::add(
$genesisPath, $hash, $file->getOwner(), $file->getFileId()
);
}
$session['permissions'] = $ownerView->getFilePermissions($path);
$session['member_id'] = (string) Member::add($session['es_id'], $uid, Helper::getRandomColor());
return $session;
}
public static function add($genesis, $hash, $owner, $fileId){
$query = \OCP\DB::prepare('
INSERT INTO ' . self::DB_TABLE . ' (`es_id`, `genesis_url`, `genesis_hash`, `owner`, `file_id`)
VALUES (?, ?, ?, ?, ?)
');
$data = array(
'es_id' => self::getUniqueSessionId(),
'genesis_url' => $genesis,
'genesis_hash' => $hash,
'owner' => $owner,
'file_id' => $fileId
);
$result = $query->execute(array_values($data));
if ($result){
return $data;
}
return false;
}
public static function getAll(){
$query = \OCP\DB::prepare('SELECT * FROM ' . self::DB_TABLE);
$result = $query->execute();
return $result->fetchAll();
}
public static function getSession($id){
$query = \OCP\DB::prepare('SELECT * FROM ' . self::DB_TABLE . ' WHERE `es_id`= ?');
$result = $query->execute(array($id));
return $result->fetchRow();
}
public static function getInfo($esId){
$query = \OCP\DB::prepare('
SELECT `s`.*, COUNT(`m`.`member_id`) AS `users`
FROM ' . self::DB_TABLE . ' AS `s`
LEFT JOIN `*PREFIX*documents_member` AS `m` ON `s`.`es_id`=`m`.`es_id`
AND `m`.`status`=' . Member::MEMBER_STATUS_ACTIVE . '
AND `m`.`uid` != ?
WHERE `s`.`es_id` = ?
GROUP BY `m`.`es_id`
');
$result = $query->execute(
array(
\OCP\User::getUser(),
$esId
)
);
$info = $result->fetchRow();
if (!is_array($info)){
$info = array();
}
return $info;
}
public static function getSessionByFileId($fileId){
$sessions = self::getSessionsByFileIds(array($fileId));
if (count($sessions) > 1){
Helper::errorLog('documents', 'more than one session found for file id ' . $fileId);
}
if (count($sessions)){
return $sessions[0];
}
return null;
}
public static function getSessionsByFileIds($fileIds){
if (!is_array($fileIds)){
$fileIds = array($fileIds);
}
$stmt = self::buildPlaceholders($fileIds);
$query = \OCP\DB::prepare('SELECT * FROM ' . self::DB_TABLE . ' WHERE `file_id` IN (' . $stmt . ')');
$result = $query->execute($fileIds);
$sessions = $result->fetchAll();
if (!is_array($sessions)){
$sessions = array();
}
return $sessions;
}
public static function getInfoByFileid($fileIds){
if (!is_array($fileIds)){
return array();
}
$stmt = self::buildPlaceholders($fileIds);
if (!$stmt){
return array();
}
$query = \OCP\DB::prepare('
SELECT `s`.*, COUNT(`m`.`member_id`) AS `users`
FROM ' . self::DB_TABLE . ' AS `s`
LEFT JOIN `*PREFIX*documents_member` AS `m` ON `s`.`es_id`=`m`.`es_id`
AND `m`.`status`=' . Member::MEMBER_STATUS_ACTIVE . '
WHERE `s`.`file_id` IN (' . $stmt . ')
GROUP BY `m`.`es_id`
');
$result = $query->execute($fileIds);
$info = $result->fetchAll();
if (!is_array($info)){
$info = array();
}
return $info;
}
public static function cleanUp($esId){
self::delete($esId);
Member::deleteBySessionId($esId);
Op::deleteBySessionId($esId);
}
public static function delete($esId){
$query = \OCP\DB::prepare('DELETE FROM ' . self::DB_TABLE . ' WHERE `es_id` = ?');
$query->execute(array($esId));
}
protected static function getUniqueSessionId(){
do{
// this prevents branching for stable5 for now:
// OC_Util::generate_random_bytes was camelCased
if (method_exists('\OC_Util', 'generate_random_bytes')){
$id = \OC_Util::generate_random_bytes(30);
} else {
$id = \OC_Util::generateRandomBytes(30);
}
}while (self::getSession($id));
return $id;
}
}

@ -56,11 +56,16 @@ class Storage {
return;
}
$session = Session::getSessionByFileId($fileId);
$sessionObj = new Db_Session();
$session = $sessionObj
->loadBy('file_id', $fileId)
->getData()
;
if (!is_array($session)){
return;
}
Session::cleanUp($session['es_id']);
Db_Session::cleanUp($session['es_id']);
}
}

Loading…
Cancel
Save