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