Page MenuHomePhorge

kolab_sync_backend_state.php
No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None

kolab_sync_backend_state.php

<?php
/**
* sql backend class for the folder state
*
* @package Syncroton
* @subpackage Backend
*/
class kolab_sync_backend_state implements Syncroton_Backend_ISyncState
{
/**
* the database adapter
*
* @var rcube_mdb2
*/
protected $db;
public function __construct()
{
$this->db = rcube::get_instance()->get_dbh();
}
/**
* create new sync state
*
* @param Syncroton_Model_ISyncState $_syncState
* @return Syncroton_Model_SyncState
*/
public function create(Syncroton_Model_ISyncState $_syncState, $_keepPreviousSyncState = true)
{
$id = sha1(mt_rand(). microtime());
$deviceId = $_syncState->device_id instanceof Syncroton_Model_IDevice ? $_syncState->device_id->id : $_syncState->device_id;
$type = $_syncState->type instanceof Syncroton_Model_IFolder ? $_syncState->type->id : $_syncState->type;
$data = is_array($_syncState->pendingdata) ? json_encode($_syncState->pendingdata) : null;
$insert[$this->db->quote_identifier('id')] = $this->db->quote($id);
$insert[$this->db->quote_identifier('device_id')] = $this->db->quote($deviceId);
$insert[$this->db->quote_identifier('type')] = $this->db->quote($type);
$insert[$this->db->quote_identifier('counter')] = $this->db->quote($_syncState->counter);
$insert[$this->db->quote_identifier('lastsync')] = $this->db->quote($_syncState->lastsync->format('Y-m-d H:i:s'));
$insert[$this->db->quote_identifier('pendingdata')] = $data ? $this->db->quote($data) : 'NULL';
$this->db->query('INSERT INTO syncroton_synckey'
. ' (' . implode(', ', array_keys($insert)) . ')' . ' VALUES(' . implode(', ', $insert) . ')');
$state = $this->get($id);
if ($_keepPreviousSyncState !== true) {
// remove all other synckeys
$this->_deleteOtherStates($state);
}
return $state;
}
protected function _deleteOtherStates(Syncroton_Model_ISyncState $_state)
{
// remove all other synckeys
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($_state->device_id);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($_state->type);
$where[] = $this->db->quote_identifier('counter') . ' <> ' . $this->db->quote($_state->counter);
$this->db->query('DELETE FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
return true;
}
/**
* @param string $_id
* @throws Syncroton_Exception_NotFound
* @return Syncroton_Model_SyncState
*/
public function get($_id)
{
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE id = ?', array($_id));
if ($state = $this->db->fetch_assoc($select)) {
$state = new Syncroton_Model_SyncState($state);
}
if (! $state instanceof Syncroton_Model_ISyncState) {
throw new Syncroton_Exception_NotFound('id not found');
}
$this->_convertFields($state);
return $state;
}
protected function _convertFields(Syncroton_Model_SyncState $state)
{
if (!empty($state->lastsync)) {
$state->lastsync = new DateTime($state->lastsync, new DateTimeZone('utc'));
}
if ($state->pendingdata) {
$state->pendingdata = json_decode($state->pendingdata);
}
}
/**
* always returns the latest syncstate
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
* @return Syncroton_Model_SyncState
*/
public function getSyncState($_deviceId, $_folderId)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$select = $this->db->limitquery('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where)
.' ORDER BY counter DESC', 0, 1);
if ($state = $this->db->fetch_assoc($select)) {
$state = new Syncroton_Model_SyncState($state);
}
if (! $state instanceof Syncroton_Model_ISyncState) {
throw new Syncroton_Exception_NotFound('id not found');
}
$this->_convertFields($state);
return $state;
}
/**
* delete all stored synckeys for given type
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
*/
public function resetState($_deviceId, $_folderId)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$this->db->query('DELETE FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
}
public function update(Syncroton_Model_ISyncState $_syncState)
{
$data = is_array($_syncState->pendingdata) ? json_encode($_syncState->pendingdata) : 'null';
$this->db->query('UPDATE syncroton_synckey SET counter = ?, lastsync = ?, pendingdata = ? WHERE id = ?',
array($_syncState->counter, $_syncState->lastsync->format('Y-m-d H:i:s'), $data, $_syncState->id));
return $this->get($_syncState->id);
}
/**
* get array of ids which got send to the client for a given class
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
*
* @return Syncroton_Model_SyncState
*/
public function validate($_deviceId, $_folderId, $_syncKey)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['type'] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey);
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
if ($state = $this->db->fetch_assoc($select)) {
$state = new Syncroton_Model_SyncState($state);
}
if (! $state instanceof Syncroton_Model_ISyncState) {
return false;
}
$this->_convertFields($state);
// check if this was the latest syncKey
$where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey + 1);
$select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
if ($moreRecentState = $this->db->fetch_assoc($select)) {
$moreRecentState = new Syncroton_Model_SyncState($moreRecentState);
}
$where = array();
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['folder_id'] = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folderId);
$where['is_deleted'] = $this->db->quote_identifier('is_deleted') . ' = 1';
// found more recent synckey => the last sync repsonse got not received by the client
if ($moreRecentState instanceof Syncroton_Model_ISyncState) {
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' = ' . $this->db->quote($state->counter);
// undelete entries marked as deleted in Syncroton_content table
$this->db->query('UPDATE syncroton_content SET is_deleted = 0 WHERE ' . implode(' AND ', $where));
// remove entries added during latest sync in Syncroton_content table
unset($where['is_deleted']);
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' > ' . $this->db->quote($state->counter);
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
else {
// finaly delete all entries marked for removal in Syncroton_content table
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
// remove all other synckeys
$this->_deleteOtherStates($state);
return $state;
}
}

File Metadata

Mime Type
text/x-php
Expires
Wed, Jul 8, 8:16 PM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1051928
Default Alt Text
kolab_sync_backend_state.php (8 KB)

Event Timeline