summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2016-08-30 08:22:34 +0200
committerGitHub <noreply@github.com>2016-08-30 08:22:34 +0200
commit4afe4bda2686ebb770b7574e87573a2cf708cd4c (patch)
tree9d7fa5cb77e2e36982b87fddad54a7a3d39ac1bc /lib
parent7278bd29872aa27ecfbb1974d373b1a3e29244df (diff)
parentdf9b509ed33ef6e3041b76b4b7ce1b22c7d81fcc (diff)
downloadnextcloud-server-4afe4bda2686ebb770b7574e87573a2cf708cd4c.tar.gz
nextcloud-server-4afe4bda2686ebb770b7574e87573a2cf708cd4c.zip
Merge pull request #891 from nextcloud/us_25810
[OC] Fix unmerged shares repair targetdecision
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Repair/RepairUnmergedShares.php50
1 files changed, 48 insertions, 2 deletions
diff --git a/lib/private/Repair/RepairUnmergedShares.php b/lib/private/Repair/RepairUnmergedShares.php
index 353877bb873..d57bc3779f8 100644
--- a/lib/private/Repair/RepairUnmergedShares.php
+++ b/lib/private/Repair/RepairUnmergedShares.php
@@ -93,7 +93,7 @@ class RepairUnmergedShares implements IRepairStep {
*/
$query = $this->connection->getQueryBuilder();
$query
- ->select('item_source', 'id', 'file_target', 'permissions', 'parent', 'share_type')
+ ->select('item_source', 'id', 'file_target', 'permissions', 'parent', 'share_type', 'stime')
->from('share')
->where($query->expr()->eq('share_type', $query->createParameter('shareType')))
->andWhere($query->expr()->in('share_with', $query->createParameter('shareWiths')))
@@ -148,6 +148,52 @@ class RepairUnmergedShares implements IRepairStep {
return $groupedShares;
}
+ private function isPotentialDuplicateName($name) {
+ return (preg_match('/\(\d+\)(\.[^\.]+)?$/', $name) === 1);
+ }
+
+ /**
+ * Decide on the best target name based on all group shares and subshares,
+ * goal is to increase the likeliness that the chosen name matches what
+ * the user is expecting.
+ *
+ * For this, we discard the entries with parenthesis "(2)".
+ * In case the user also renamed the duplicates to a legitimate name, this logic
+ * will still pick the most recent one as it's the one the user is most likely to
+ * remember renaming.
+ *
+ * If no suitable subshare is found, use the least recent group share instead.
+ *
+ * @param array $groupShares group share entries
+ * @param array $subShares sub share entries
+ *
+ * @return string chosen target name
+ */
+ private function findBestTargetName($groupShares, $subShares) {
+ $pickedShare = null;
+ // sort by stime, this also properly sorts the direct user share if any
+ @usort($subShares, function($a, $b) {
+ return ((int)$a['stime'] - (int)$b['stime']);
+ });
+
+ foreach ($subShares as $subShare) {
+ // skip entries that have parenthesis with numbers
+ if ($this->isPotentialDuplicateName($subShare['file_target'])) {
+ continue;
+ }
+ // pick any share found that would match, the last being the most recent
+ $pickedShare = $subShare;
+ }
+
+ // no suitable subshare found
+ if ($pickedShare === null) {
+ // use least recent group share target instead
+ $pickedShare = $groupShares[0];
+ }
+
+ return $pickedShare['file_target'];
+ }
+
/**
* Fix the given received share represented by the set of group shares
* and matching sub shares
@@ -171,7 +217,7 @@ class RepairUnmergedShares implements IRepairStep {
return false;
}
- $targetPath = $groupShares[0]['file_target'];
+ $targetPath = $this->findBestTargetName($groupShares, $subShares);
// check whether the user opted out completely of all subshares
$optedOut = true;