Example #1
0
 /**
  * handle options request
  */
 protected function _handleOptions()
 {
     $command = new Syncroton_Command_Options();
     $this->_sendHeaders($command->getHeaders());
 }
Example #2
0
 /**
  * generate FolderSync response
  *
  * @todo changes are missing in response (folder got renamed for example)
  */
 public function getResponse()
 {
     $folderSync = $this->_outputDom->documentElement;
     // invalid synckey provided
     if (!$this->_syncState instanceof Syncroton_Model_SyncState) {
         if ($this->_logger instanceof Syncroton_Log) {
             $this->_logger->info(__METHOD__ . '::' . __LINE__ . " invalid synckey provided. FolderSync 0 needed.");
         }
         $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_INVALID_SYNC_KEY));
         return $this->_outputDom;
     }
     // send headers from options command also when FolderSync SyncKey is 0
     if ($this->_syncState->counter == 0) {
         $optionsCommand = new Syncroton_Command_Options();
         $this->_headers = array_merge($this->_headers, $optionsCommand->getHeaders());
     }
     $adds = array();
     $updates = array();
     $deletes = array();
     foreach ($this->_classes as $class) {
         try {
             $dataController = Syncroton_Data_Factory::factory($class, $this->_device, $this->_syncTimeStamp);
         } catch (Exception $e) {
             // backend not defined
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->info(__METHOD__ . '::' . __LINE__ . " no data backend defined for class: " . $class);
             }
             continue;
         }
         try {
             // retrieve all folders available in data backend
             $serverFolders = $dataController->getAllFolders();
             // retrieve all folders sent to client
             $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class);
             if ($this->_syncState->counter > 0) {
                 // retrieve all folders changed since last sync
                 $changedFolders = $dataController->getChangedFolders($this->_syncState->lastsync, $this->_syncTimeStamp);
             } else {
                 $changedFolders = array();
             }
             if ($class == 'Contacts' && sizeof($serverFolders) > 2) {
                 //debug($this->_syncState->lastsync);
                 //die;
             }
             // only folders which were sent to the client already are allowed to be in $changedFolders
             $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class);
             $changedFolders = array_intersect_key($changedFolders, $clientFolders);
         } catch (Exception $e) {
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->critical(__METHOD__ . '::' . __LINE__ . " Syncing folder hierarchy failed: " . $e->getMessage());
             }
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Syncing folder hierarchy failed: " . $e->getTraceAsString());
             }
             // The Status element is global for all collections. If one collection fails,
             // a failure status MUST be returned for all collections.
             if ($e instanceof Syncroton_Exception_Status) {
                 $status = $e->getCode();
             } else {
                 $status = Syncroton_Exception_Status_FolderSync::UNKNOWN_ERROR;
             }
             $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', $status));
             return $this->_outputDom;
         }
         $serverFoldersIds = array_keys($serverFolders);
         // is this the first sync?
         if ($this->_syncState->counter == 0) {
             $clientFoldersIds = array();
         } else {
             $clientFoldersIds = array_keys($clientFolders);
         }
         // calculate added entries
         $serverDiff = array_diff($serverFoldersIds, $clientFoldersIds);
         foreach ($serverDiff as $serverFolderId) {
             // have we created a folderObject in syncroton_folder before?
             if (isset($clientFolders[$serverFolderId])) {
                 $add = $clientFolders[$serverFolderId];
             } else {
                 $add = $serverFolders[$serverFolderId];
                 $add->creationTime = $this->_syncTimeStamp;
                 $add->deviceId = $this->_device;
                 unset($add->id);
             }
             $add->class = $class;
             $adds[] = $add;
         }
         // calculate changed entries
         foreach ($changedFolders as $changedFolder) {
             $change = $clientFolders[$changedFolder->serverId];
             $change->displayName = $changedFolder->displayName;
             $change->parentId = $changedFolder->parentId;
             $change->type = $changedFolder->type;
             $updates[] = $change;
         }
         // calculate deleted entries
         $serverDiff = array_diff($clientFoldersIds, $serverFoldersIds);
         foreach ($serverDiff as $serverFolderId) {
             $deletes[] = $clientFolders[$serverFolderId];
         }
     }
     $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_SUCCESS));
     $count = count($adds) + count($updates) + count($deletes);
     if ($count > 0) {
         $this->_syncState->counter++;
         $this->_syncState->lastsync = $this->_syncTimeStamp;
     }
     // create xml output
     $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter));
     $changes = $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Changes'));
     $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Count', $count));
     foreach ($adds as $folder) {
         $add = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Add'));
         $folder->appendXML($add, $this->_device);
         // store folder in backend
         if (empty($folder->id)) {
             $this->_folderBackend->create($folder);
         }
     }
     foreach ($updates as $folder) {
         $update = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Update'));
         $folder->appendXML($update, $this->_device);
         $this->_folderBackend->update($folder);
     }
     foreach ($deletes as $folder) {
         $delete = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Delete'));
         $delete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->serverId));
         $this->_folderBackend->delete($folder);
     }
     if (empty($this->_syncState->id)) {
         $this->_syncStateBackend->create($this->_syncState);
     } else {
         $this->_syncStateBackend->update($this->_syncState);
     }
     return $this->_outputDom;
 }