Remove a collection from the cache.
public removeCollection ( string $id, boolean $purge = true ) | ||
$id | string | The collection id. |
$purge | boolean | If true, completely remove the collection entry otherwise, just resets the synckey. |
/** * Check for an update FILTERTYPE * * @param string $id The collection id to check * @param string $filter The new filter value. * * @return boolean True if filtertype passed, false if it has changed. */ public function checkFilterType($id, $filter) { $cc = $this->_cache->getCollections(); if (!empty($cc[$id]['filtertype']) && !is_null($filter) && $cc[$id]['filtertype'] != $filter) { $this->_cache->removeCollection($id, true); $this->_cache->save(); $this->_logger->info('Invalidating SYNCKEY and removing collection - found updated filtertype'); return false; } return true; }
/** * Prepares the syncCache for a partial sync request and checks that * it is allowed. * * MS-ASCMD 2.2.3.124 * * @return boolean True if parital sync is possible, false otherwise. */ public function initPartialSync() { // Need this for all PARTIAL sync requests. $this->_tempSyncCache = clone $this->_cache; // Short circuit if we only have a changed ping/wait interval. if (empty($this->_collections)) { $emptyCollections = true; $this->_logger->info(sprintf('[%s] No collections in collection handler, loading full collection set from cache.', $this->_procid)); $this->loadCollectionsFromCache(); } else { // Collect collection options sent from client and compare against // last known collection options to determine which collections // changed. $emptyCollections = false; $c = $this->_tempSyncCache->getCollections(); foreach ($this->_collections as $key => $value) { // Collections from cache might not all have synckeys. if (empty($c[$key])) { continue; } $v1 = $value; foreach ($v1 as $k => $o) { if (is_null($o)) { unset($v1[$k]); } } unset($v1['id'], $v1['serverid'], $v1['clientids'], $v1['fetchids'], $v1['getchanges'], $v1['changeids'], $v1['pingable'], $v1['class'], $v1['synckey'], $v1['lastsynckey']); $v2 = $c[$key]; foreach ($v2 as $k => $o) { if (is_null($o)) { unset($v2[$k]); } } unset($v2['id'], $v2['serverid'], $v2['pingable'], $v2['class'], $v2['synckey'], $v2['lastsynckey']); ksort($v1); if (isset($v1['bodyprefs'])) { ksort($v1['bodyprefs']); foreach (array_keys($v1['bodyprefs']) as $k) { if (is_array($v1['bodyprefs'][$k])) { ksort($v1['bodyprefs'][$k]); } } } ksort($v2); if (isset($v2['bodyprefs'])) { ksort($v2['bodyprefs']); foreach (array_keys($v2['bodyprefs']) as $k) { if (is_array($v2['bodyprefs'][$k])) { ksort($v2['bodyprefs'][$k]); } } } if (md5(serialize($v1)) == md5(serialize($v2))) { $this->_unchangedCount++; } // Unset in tempSyncCache, since we have it from device. $this->_tempSyncCache->removeCollection($key); // Populate _collections with missing collection data not sent. $this->_getMissingCollectionsFromCache(); } } // Ensure we are both talking about the same synckey. foreach ($this->_collections as $value) { if (isset($value['synckey'])) { if (isset($this->_cache->confirmed_synckeys[$value['synckey']])) { $this->_logger->info(sprintf('Removed %s from confirmed_synckeys', $value['synckey'])); $this->_cache->removeConfirmedKey($value['synckey']); } $this->_synckeyCount++; } } if (!$this->_checkConfirmedKeys()) { $this->_logger->warn('Some synckeys were not confirmed. Requesting full SYNC'); $this->save(); return false; } if (!$emptyCollections && $this->_haveNoChangesInPartialSync()) { $this->_logger->warn(sprintf('[%s] Partial Request with completely unchanged collections. Request a full SYNC', $this->_procid)); return false; } return true; }
/** * Reset the sync state for this device, for the specified collection. * * @param string $id The collection to reset. * * @return void * @throws Horde_ActiveSync_Exception */ protected function _resetDeviceState($id) { $this->_logger->info(sprintf('[%s] Resetting device state for device: %s, user: %s, and collection: %s.', $this->_procid, $this->_deviceInfo->id, $this->_deviceInfo->user, $id)); $state_query = 'DELETE FROM ' . $this->_syncStateTable . ' WHERE sync_devid = ? AND sync_folderid = ? AND sync_user = ?'; $map_query = 'DELETE FROM ' . $this->_syncMapTable . ' WHERE sync_devid = ? AND sync_folderid = ? AND sync_user = ?'; $mailmap_query = 'DELETE FROM ' . $this->_syncMailMapTable . ' WHERE sync_devid = ? AND sync_folderid = ? AND sync_user = ?'; try { $this->_db->delete($state_query, array($this->_deviceInfo->id, $id, $this->_deviceInfo->user)); $this->_db->delete($map_query, array($this->_deviceInfo->id, $id, $this->_deviceInfo->user)); $this->_db->delete($mailmap_query, array($this->_deviceInfo->id, $id, $this->_deviceInfo->user)); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } // Remove the collection data from the synccache as well. $cache = new Horde_ActiveSync_SyncCache($this, $this->_deviceInfo->id, $this->_deviceInfo->user, $this->_logger); if ($id != Horde_ActiveSync::REQUEST_TYPE_FOLDERSYNC) { $cache->removeCollection($id, false); } else { $this->_logger->notice(sprintf('[%s] Clearing foldersync state from synccache.', $this->_procid)); $cache->clearFolders(); $cache->clearCollections(); $cache->hierarchy = '0'; } $cache->save(); }
/** * Reset the sync state for this device, for the specified collection. * * @param string $id The collection to reset. * * @return void * @throws Horde_ActiveSync_Exception */ protected function _resetDeviceState($id) { $this->_logger->info(sprintf('[%s] Resetting device state for device: %s, user: %s, and collection: %s.', $this->_procid, $this->_deviceInfo->id, $this->_deviceInfo->user, $id)); $query = array(self::SYNC_DEVID => $this->_deviceInfo->id, self::SYNC_FOLDERID => $id, self::SYNC_USER => $this->_deviceInfo->user); try { $this->_db->selectCollection(self::COLLECTION_STATE)->remove($query); $this->_db->selectCollection(self::COLLECTION_MAP)->remove($query); $this->_db->selectCollection(self::COLLECTION_MAILMAP)->remove($query); } catch (Exception $e) { $this->_logger->err($e->getMessage()); throw new Horde_ActiveSync_Exception($e); } // Remove the collection data from the synccache as well. $cache = new Horde_ActiveSync_SyncCache($this, $this->_deviceInfo->id, $this->_deviceInfo->user, $this->_logger); if ($id != Horde_ActiveSync::REQUEST_TYPE_FOLDERSYNC) { $cache->removeCollection($id, false); } else { $this->_logger->notice(sprintf('[%s] Clearing foldersync state from synccache.', $this->_procid)); $cache->clearFolders(); $cache->clearCollections(); $cache->hierarchy = '0'; } $cache->save(); }
/** * Prepares the syncCache for a partial sync request and checks that * it is allowed. * * @return boolean True if parital sync is possible, false otherwise. */ public function initPartialSync() { // PARTIAL is allowed without a <collection> tag if the waitinterval, // heartbeat, or windowsize changed. So, short circuit the logic for // checking for changed collections in this case. if (empty($this->_collections)) { $this->_logger->info('No collections in collection handler, loading full collection set from cache.'); $this->loadCollectionsFromCache(); // Need this for all PARTIAL sync requests. $this->_tempSyncCache = clone $this->_cache; foreach ($this->_collections as $value) { // Remove keys from confirmed synckeys array and count them if (isset($value['synckey'])) { if (isset($this->_cache->confirmed_synckeys[$value['synckey']])) { $this->_logger->info(sprintf('Removed %s from confirmed_synckeys', $value['synckey'])); $this->_cache->removeConfirmedKey($value['synckey']); } $this->_synckeyCount++; } } if (!$this->_checkConfirmedKeys()) { $this->_logger->err('Some synckeys were not confirmed. Requesting full SYNC'); $this->save(); return false; } return true; } $this->_tempSyncCache = clone $this->_cache; $c = $this->_tempSyncCache->getCollections(); foreach ($this->_collections as $key => $value) { // Collections from cache might not all have synckeys. if (!empty($c[$key])) { $v1 = $value; foreach ($v1 as $k => $o) { if (is_null($o)) { unset($v1[$k]); } } unset($v1['id'], $v1['serverid'], $v1['clientids'], $v1['fetchids'], $v1['getchanges'], $v1['changeids'], $v1['pingable'], $v1['class'], $v1['synckey'], $v1['lastsynckey']); $v2 = $c[$key]; foreach ($v2 as $k => $o) { if (is_null($o)) { unset($v2[$k]); } } unset($v2['id'], $v2['serverid'], $v2['pingable'], $v2['class'], $v2['synckey'], $v2['lastsynckey']); ksort($v1); if (isset($v1['bodyprefs'])) { ksort($v1['bodyprefs']); foreach (array_keys($v1['bodyprefs']) as $k) { if (is_array($v1['bodyprefs'][$k])) { ksort($v1['bodyprefs'][$k]); } } } ksort($v2); if (isset($v2['bodyprefs'])) { ksort($v2['bodyprefs']); foreach (array_keys($v2['bodyprefs']) as $k) { if (is_array($v2['bodyprefs'][$k])) { ksort($v2['bodyprefs'][$k]); } } } if (md5(serialize($v1)) == md5(serialize($v2))) { $this->_unchangedCount++; } // Unset in tempSyncCache, since we have it from device. // Afterwards, anything left in tempSyncCache needs to be added // to _collections (this is done in // self::_haveNoChangesInPartialSync()). $this->_tempSyncCache->removeCollection($key); // Remove keys from confirmed synckeys array and count them. if (isset($value['synckey'])) { if (isset($this->_cache->confirmed_synckeys[$value['synckey']])) { $this->_logger->info(sprintf('Removed %s from confirmed_synckeys', $value['synckey'])); $this->_cache->removeConfirmedKey($value['synckey']); } $this->_synckeyCount++; } } } if (!$this->_checkConfirmedKeys()) { $this->_logger->err('Some synckeys were not confirmed. Requesting full SYNC'); $this->save(); return false; } if ($this->_haveNoChangesInPartialSync()) { $this->_logger->warn(sprintf('[%s] Partial Request with completely unchanged collections. Request a full SYNC', $this->_procid)); return false; } return true; }