Completed
Push — master ( e95e7d...73554a )
by Robin
15:11
created
lib/private/Repair/NC13/RepairInvalidPaths.php 2 patches
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -29,164 +29,164 @@
 block discarded – undo
29 29
 use OCP\Migration\IRepairStep;
30 30
 
31 31
 class RepairInvalidPaths implements IRepairStep {
32
-	const MAX_ROWS = 1000;
33
-
34
-	/** @var IDBConnection */
35
-	private $connection;
36
-	/** @var IConfig */
37
-	private $config;
38
-
39
-	private $getIdQuery;
40
-	private $updateQuery;
41
-	private $reparentQuery;
42
-	private $deleteQuery;
43
-
44
-	public function __construct(IDBConnection $connection, IConfig $config) {
45
-		$this->connection = $connection;
46
-		$this->config = $config;
47
-	}
48
-
49
-
50
-	public function getName() {
51
-		return 'Repair invalid paths in file cache';
52
-	}
53
-
54
-	/**
55
-	 * @return \Generator
56
-	 * @suppress SqlInjectionChecker
57
-	 */
58
-	private function getInvalidEntries() {
59
-		$builder = $this->connection->getQueryBuilder();
60
-
61
-		$computedPath = $builder->func()->concat(
62
-			'p.path',
63
-			$builder->func()->concat($builder->createNamedParameter('/'), 'f.name')
64
-		);
65
-
66
-		//select f.path, f.parent,p.path from oc_filecache f inner join oc_filecache p on f.parent=p.fileid and p.path!='' where f.path != p.path || '/' || f.name;
67
-		$builder->select('f.fileid', 'f.path', 'f.name', 'f.parent', 'f.storage')
68
-			->selectAlias('p.path', 'parent_path')
69
-			->selectAlias('p.storage', 'parent_storage')
70
-			->from('filecache', 'f')
71
-			->innerJoin('f', 'filecache', 'p', $builder->expr()->andX(
72
-				$builder->expr()->eq('f.parent', 'p.fileid'),
73
-				$builder->expr()->nonEmptyString('p.name')
74
-			))
75
-			->where($builder->expr()->neq('f.path', $computedPath))
76
-			->setMaxResults(self::MAX_ROWS);
77
-
78
-		do {
79
-			$result = $builder->execute();
80
-			$rows = $result->fetchAll();
81
-			foreach ($rows as $row) {
82
-				yield $row;
83
-			}
84
-			$result->closeCursor();
85
-		} while (count($rows) > 0);
86
-	}
87
-
88
-	private function getId($storage, $path) {
89
-		if (!$this->getIdQuery) {
90
-			$builder = $this->connection->getQueryBuilder();
91
-
92
-			$this->getIdQuery = $builder->select('fileid')
93
-				->from('filecache')
94
-				->where($builder->expr()->eq('storage', $builder->createParameter('storage')))
95
-				->andWhere($builder->expr()->eq('path_hash', $builder->createParameter('path_hash')));
96
-		}
97
-
98
-		$this->getIdQuery->setParameter('storage', $storage, IQueryBuilder::PARAM_INT);
99
-		$this->getIdQuery->setParameter('path_hash', md5($path));
100
-
101
-		return $this->getIdQuery->execute()->fetchColumn();
102
-	}
103
-
104
-	/**
105
-	 * @param string $fileid
106
-	 * @param string $newPath
107
-	 * @param string $newStorage
108
-	 * @suppress SqlInjectionChecker
109
-	 */
110
-	private function update($fileid, $newPath, $newStorage) {
111
-		if (!$this->updateQuery) {
112
-			$builder = $this->connection->getQueryBuilder();
113
-
114
-			$this->updateQuery = $builder->update('filecache')
115
-				->set('path', $builder->createParameter('newpath'))
116
-				->set('path_hash', $builder->func()->md5($builder->createParameter('newpath')))
117
-				->set('storage', $builder->createParameter('newstorage'))
118
-				->where($builder->expr()->eq('fileid', $builder->createParameter('fileid')));
119
-		}
120
-
121
-		$this->updateQuery->setParameter('newpath', $newPath);
122
-		$this->updateQuery->setParameter('newstorage', $newStorage);
123
-		$this->updateQuery->setParameter('fileid', $fileid, IQueryBuilder::PARAM_INT);
124
-
125
-		$this->updateQuery->execute();
126
-	}
127
-
128
-	private function reparent($from, $to) {
129
-		if (!$this->reparentQuery) {
130
-			$builder = $this->connection->getQueryBuilder();
131
-
132
-			$this->reparentQuery = $builder->update('filecache')
133
-				->set('parent', $builder->createParameter('to'))
134
-				->where($builder->expr()->eq('fileid', $builder->createParameter('from')));
135
-		}
136
-
137
-		$this->reparentQuery->setParameter('from', $from);
138
-		$this->reparentQuery->setParameter('to', $to);
139
-
140
-		$this->reparentQuery->execute();
141
-	}
142
-
143
-	private function delete($fileid) {
144
-		if (!$this->deleteQuery) {
145
-			$builder = $this->connection->getQueryBuilder();
146
-
147
-			$this->deleteQuery = $builder->delete('filecache')
148
-				->where($builder->expr()->eq('fileid', $builder->createParameter('fileid')));
149
-		}
150
-
151
-		$this->deleteQuery->setParameter('fileid', $fileid, IQueryBuilder::PARAM_INT);
152
-
153
-		$this->deleteQuery->execute();
154
-	}
155
-
156
-	private function repair() {
157
-		$this->connection->beginTransaction();
158
-		$entries = $this->getInvalidEntries();
159
-		$count = 0;
160
-		foreach ($entries as $entry) {
161
-			$count++;
162
-			$calculatedPath = $entry['parent_path'] . '/' . $entry['name'];
163
-			if ($newId = $this->getId($entry['parent_storage'], $calculatedPath)) {
164
-				// a new entry with the correct path has already been created, reuse that one and delete the incorrect entry
165
-				$this->reparent($entry['fileid'], $newId);
166
-				$this->delete($entry['fileid']);
167
-			} else {
168
-				$this->update($entry['fileid'], $calculatedPath, $entry['parent_storage']);
169
-			}
170
-		}
171
-		$this->connection->commit();
172
-		return $count;
173
-	}
174
-
175
-	private function shouldRun() {
176
-		$versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
177
-
178
-		// was added to 11.0.5.2, 12.0.0.30 and 13.0.0.1
179
-		$shouldRun = version_compare($versionFromBeforeUpdate, '11.0.5.2', '<');
180
-		$shouldRun |= version_compare($versionFromBeforeUpdate, '12.0.0.0', '>=') && version_compare($versionFromBeforeUpdate, '12.0.0.30', '<');
181
-		$shouldRun |= version_compare($versionFromBeforeUpdate, '13.0.0.0', '==');
182
-		return $shouldRun;
183
-	}
184
-
185
-	public function run(IOutput $output) {
186
-		if ($this->shouldRun()) {
187
-			$count = $this->repair();
188
-
189
-			$output->info('Repaired ' . $count . ' paths');
190
-		}
191
-	}
32
+    const MAX_ROWS = 1000;
33
+
34
+    /** @var IDBConnection */
35
+    private $connection;
36
+    /** @var IConfig */
37
+    private $config;
38
+
39
+    private $getIdQuery;
40
+    private $updateQuery;
41
+    private $reparentQuery;
42
+    private $deleteQuery;
43
+
44
+    public function __construct(IDBConnection $connection, IConfig $config) {
45
+        $this->connection = $connection;
46
+        $this->config = $config;
47
+    }
48
+
49
+
50
+    public function getName() {
51
+        return 'Repair invalid paths in file cache';
52
+    }
53
+
54
+    /**
55
+     * @return \Generator
56
+     * @suppress SqlInjectionChecker
57
+     */
58
+    private function getInvalidEntries() {
59
+        $builder = $this->connection->getQueryBuilder();
60
+
61
+        $computedPath = $builder->func()->concat(
62
+            'p.path',
63
+            $builder->func()->concat($builder->createNamedParameter('/'), 'f.name')
64
+        );
65
+
66
+        //select f.path, f.parent,p.path from oc_filecache f inner join oc_filecache p on f.parent=p.fileid and p.path!='' where f.path != p.path || '/' || f.name;
67
+        $builder->select('f.fileid', 'f.path', 'f.name', 'f.parent', 'f.storage')
68
+            ->selectAlias('p.path', 'parent_path')
69
+            ->selectAlias('p.storage', 'parent_storage')
70
+            ->from('filecache', 'f')
71
+            ->innerJoin('f', 'filecache', 'p', $builder->expr()->andX(
72
+                $builder->expr()->eq('f.parent', 'p.fileid'),
73
+                $builder->expr()->nonEmptyString('p.name')
74
+            ))
75
+            ->where($builder->expr()->neq('f.path', $computedPath))
76
+            ->setMaxResults(self::MAX_ROWS);
77
+
78
+        do {
79
+            $result = $builder->execute();
80
+            $rows = $result->fetchAll();
81
+            foreach ($rows as $row) {
82
+                yield $row;
83
+            }
84
+            $result->closeCursor();
85
+        } while (count($rows) > 0);
86
+    }
87
+
88
+    private function getId($storage, $path) {
89
+        if (!$this->getIdQuery) {
90
+            $builder = $this->connection->getQueryBuilder();
91
+
92
+            $this->getIdQuery = $builder->select('fileid')
93
+                ->from('filecache')
94
+                ->where($builder->expr()->eq('storage', $builder->createParameter('storage')))
95
+                ->andWhere($builder->expr()->eq('path_hash', $builder->createParameter('path_hash')));
96
+        }
97
+
98
+        $this->getIdQuery->setParameter('storage', $storage, IQueryBuilder::PARAM_INT);
99
+        $this->getIdQuery->setParameter('path_hash', md5($path));
100
+
101
+        return $this->getIdQuery->execute()->fetchColumn();
102
+    }
103
+
104
+    /**
105
+     * @param string $fileid
106
+     * @param string $newPath
107
+     * @param string $newStorage
108
+     * @suppress SqlInjectionChecker
109
+     */
110
+    private function update($fileid, $newPath, $newStorage) {
111
+        if (!$this->updateQuery) {
112
+            $builder = $this->connection->getQueryBuilder();
113
+
114
+            $this->updateQuery = $builder->update('filecache')
115
+                ->set('path', $builder->createParameter('newpath'))
116
+                ->set('path_hash', $builder->func()->md5($builder->createParameter('newpath')))
117
+                ->set('storage', $builder->createParameter('newstorage'))
118
+                ->where($builder->expr()->eq('fileid', $builder->createParameter('fileid')));
119
+        }
120
+
121
+        $this->updateQuery->setParameter('newpath', $newPath);
122
+        $this->updateQuery->setParameter('newstorage', $newStorage);
123
+        $this->updateQuery->setParameter('fileid', $fileid, IQueryBuilder::PARAM_INT);
124
+
125
+        $this->updateQuery->execute();
126
+    }
127
+
128
+    private function reparent($from, $to) {
129
+        if (!$this->reparentQuery) {
130
+            $builder = $this->connection->getQueryBuilder();
131
+
132
+            $this->reparentQuery = $builder->update('filecache')
133
+                ->set('parent', $builder->createParameter('to'))
134
+                ->where($builder->expr()->eq('fileid', $builder->createParameter('from')));
135
+        }
136
+
137
+        $this->reparentQuery->setParameter('from', $from);
138
+        $this->reparentQuery->setParameter('to', $to);
139
+
140
+        $this->reparentQuery->execute();
141
+    }
142
+
143
+    private function delete($fileid) {
144
+        if (!$this->deleteQuery) {
145
+            $builder = $this->connection->getQueryBuilder();
146
+
147
+            $this->deleteQuery = $builder->delete('filecache')
148
+                ->where($builder->expr()->eq('fileid', $builder->createParameter('fileid')));
149
+        }
150
+
151
+        $this->deleteQuery->setParameter('fileid', $fileid, IQueryBuilder::PARAM_INT);
152
+
153
+        $this->deleteQuery->execute();
154
+    }
155
+
156
+    private function repair() {
157
+        $this->connection->beginTransaction();
158
+        $entries = $this->getInvalidEntries();
159
+        $count = 0;
160
+        foreach ($entries as $entry) {
161
+            $count++;
162
+            $calculatedPath = $entry['parent_path'] . '/' . $entry['name'];
163
+            if ($newId = $this->getId($entry['parent_storage'], $calculatedPath)) {
164
+                // a new entry with the correct path has already been created, reuse that one and delete the incorrect entry
165
+                $this->reparent($entry['fileid'], $newId);
166
+                $this->delete($entry['fileid']);
167
+            } else {
168
+                $this->update($entry['fileid'], $calculatedPath, $entry['parent_storage']);
169
+            }
170
+        }
171
+        $this->connection->commit();
172
+        return $count;
173
+    }
174
+
175
+    private function shouldRun() {
176
+        $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
177
+
178
+        // was added to 11.0.5.2, 12.0.0.30 and 13.0.0.1
179
+        $shouldRun = version_compare($versionFromBeforeUpdate, '11.0.5.2', '<');
180
+        $shouldRun |= version_compare($versionFromBeforeUpdate, '12.0.0.0', '>=') && version_compare($versionFromBeforeUpdate, '12.0.0.30', '<');
181
+        $shouldRun |= version_compare($versionFromBeforeUpdate, '13.0.0.0', '==');
182
+        return $shouldRun;
183
+    }
184
+
185
+    public function run(IOutput $output) {
186
+        if ($this->shouldRun()) {
187
+            $count = $this->repair();
188
+
189
+            $output->info('Repaired ' . $count . ' paths');
190
+        }
191
+    }
192 192
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
 		$count = 0;
160 160
 		foreach ($entries as $entry) {
161 161
 			$count++;
162
-			$calculatedPath = $entry['parent_path'] . '/' . $entry['name'];
162
+			$calculatedPath = $entry['parent_path'].'/'.$entry['name'];
163 163
 			if ($newId = $this->getId($entry['parent_storage'], $calculatedPath)) {
164 164
 				// a new entry with the correct path has already been created, reuse that one and delete the incorrect entry
165 165
 				$this->reparent($entry['fileid'], $newId);
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
 		if ($this->shouldRun()) {
187 187
 			$count = $this->repair();
188 188
 
189
-			$output->info('Repaired ' . $count . ' paths');
189
+			$output->info('Repaired '.$count.' paths');
190 190
 		}
191 191
 	}
192 192
 }
Please login to merge, or discard this patch.