1<?php 2 3namespace Sabre\DAV\Sync; 4 5use Sabre\DAV; 6 7/** 8 * This mocks a ISyncCollection, for unittesting. 9 * 10 * This object behaves the same as SimpleCollection. Call addChange to update 11 * the 'changelog' that this class uses for the collection. 12 * 13 * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 14 * @author Evert Pot (http://evertpot.com/) 15 * @license http://sabre.io/license/ Modified BSD License 16 */ 17class MockSyncCollection extends DAV\SimpleCollection implements ISyncCollection { 18 19 public $changeLog = []; 20 21 public $token = null; 22 23 /** 24 * This method returns the current sync-token for this collection. 25 * This can be any string. 26 * 27 * If null is returned from this function, the plugin assumes there's no 28 * sync information available. 29 * 30 * @return string|null 31 */ 32 public function getSyncToken() { 33 34 // Will be 'null' in the first round, and will increment ever after. 35 return $this->token; 36 37 } 38 39 public function addChange(array $added, array $modified, array $deleted) { 40 41 $this->token++; 42 $this->changeLog[$this->token] = [ 43 'added' => $added, 44 'modified' => $modified, 45 'deleted' => $deleted, 46 ]; 47 48 } 49 50 /** 51 * The getChanges method returns all the changes that have happened, since 52 * the specified syncToken and the current collection. 53 * 54 * This function should return an array, such as the following: 55 * 56 * array( 57 * 'syncToken' => 'The current synctoken', 58 * 'modified' => array( 59 * 'new.txt', 60 * ), 61 * 'deleted' => array( 62 * 'foo.php.bak', 63 * 'old.txt' 64 * ) 65 * ); 66 * 67 * The syncToken property should reflect the *current* syncToken of the 68 * collection, as reported getSyncToken(). This is needed here too, to 69 * ensure the operation is atomic. 70 * 71 * If the syncToken is specified as null, this is an initial sync, and all 72 * members should be reported. 73 * 74 * The modified property is an array of nodenames that have changed since 75 * the last token. 76 * 77 * The deleted property is an array with nodenames, that have been deleted 78 * from collection. 79 * 80 * The second argument is basically the 'depth' of the report. If it's 1, 81 * you only have to report changes that happened only directly in immediate 82 * descendants. If it's 2, it should also include changes from the nodes 83 * below the child collections. (grandchildren) 84 * 85 * The third (optional) argument allows a client to specify how many 86 * results should be returned at most. If the limit is not specified, it 87 * should be treated as infinite. 88 * 89 * If the limit (infinite or not) is higher than you're willing to return, 90 * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception. 91 * 92 * If the syncToken is expired (due to data cleanup) or unknown, you must 93 * return null. 94 * 95 * The limit is 'suggestive'. You are free to ignore it. 96 * 97 * @param string $syncToken 98 * @param int $syncLevel 99 * @param int $limit 100 * @return array 101 */ 102 public function getChanges($syncToken, $syncLevel, $limit = null) { 103 104 // This is an initial sync 105 if (is_null($syncToken)) { 106 return [ 107 'added' => array_map( 108 function($item) { 109 return $item->getName(); 110 }, $this->getChildren() 111 ), 112 'modified' => [], 113 'deleted' => [], 114 'syncToken' => $this->getSyncToken(), 115 ]; 116 } 117 118 if (!is_int($syncToken) && !ctype_digit($syncToken)) { 119 120 return null; 121 122 } 123 if (is_null($this->token)) return null; 124 125 $added = []; 126 $modified = []; 127 $deleted = []; 128 129 foreach($this->changeLog as $token=>$change) { 130 131 if ($token > $syncToken) { 132 133 $added = array_merge($added, $change['added']); 134 $modified = array_merge($modified, $change['modified']); 135 $deleted = array_merge($deleted, $change['deleted']); 136 137 if ($limit) { 138 // If there's a limit, we may need to cut things off. 139 // This alghorithm is weird and stupid, but it works. 140 $left = $limit - (count($modified) + count($deleted)); 141 if ($left>0) continue; 142 if ($left===0) break; 143 if ($left<0) { 144 $modified = array_slice($modified, 0, $left); 145 } 146 $left = $limit - (count($modified) + count($deleted)); 147 if ($left===0) break; 148 if ($left<0) { 149 $deleted = array_slice($deleted, 0, $left); 150 } 151 break; 152 153 } 154 155 } 156 157 } 158 159 return array( 160 'syncToken' => $this->token, 161 'added' => $added, 162 'modified' => $modified, 163 'deleted' => $deleted, 164 ); 165 166 } 167 168 169} 170