Passed
Push — master ( 3c693d...ccd5ca )
by Roeland
28:56 queued 14:09
created

MoveAvatarsBackgroundJob::moveAvatars()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 30
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 22
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 30
rs 8.9457
1
<?php
2
/**
3
 * @copyright 2016 Roeland Jago Douma <[email protected]>
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Morris Jobke <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 *
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
namespace OC\Repair\Owncloud;
26
27
use OC\BackgroundJob\QueuedJob;
28
use OCP\Files\IRootFolder;
29
use OCP\Files\NotFoundException;
30
use OCP\Files\Storage;
31
use OCP\IAvatarManager;
32
use OCP\IUser;
33
use OCP\IUserManager;
34
use Psr\Log\LoggerInterface;
35
36
class MoveAvatarsBackgroundJob extends QueuedJob {
37
38
	/** @var IUserManager */
39
	private $userManager;
40
41
	/** @var LoggerInterface */
42
	private $logger;
43
44
	/** @var IAvatarManager */
45
	private $avatarManager;
46
47
	/** @var Storage */
48
	private $owncloudAvatarStorage;
49
50
	public function __construct(IUserManager $userManager, LoggerInterface $logger, IAvatarManager $avatarManager, IRootFolder $rootFolder) {
51
		$this->userManager = $userManager;
52
		$this->logger = $logger;
53
		$this->avatarManager = $avatarManager;
54
		try {
55
			$this->owncloudAvatarStorage = $rootFolder->get('avatars')->getStorage();
56
		} catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
57
		}
58
	}
59
60
	public function run($arguments) {
61
		$this->logger->info('Started migrating avatars to AppData folder');
62
		$this->moveAvatars();
63
		$this->logger->info('All avatars migrated to AppData folder');
64
	}
65
66
	private function moveAvatars(): void {
67
		if (!$this->owncloudAvatarStorage) {
68
			$this->logger->info('No legacy avatars available, skipping migration');
69
			return;
70
		}
71
72
		$counter = 0;
73
		$this->userManager->callForSeenUsers(function (IUser $user) use ($counter) {
74
			$uid = $user->getUID();
75
76
			$path = 'avatars/' . $this->buildOwnCloudAvatarPath($uid);
77
			$avatar = $this->avatarManager->getAvatar($uid);
78
			try {
79
				$avatarPath = $path . '/avatar.' . $this->getExtension($path);
80
				$resource = $this->owncloudAvatarStorage->fopen($avatarPath, 'r');
81
				if ($resource) {
0 ignored issues
show
introduced by
$resource is of type false|resource, thus it always evaluated to false.
Loading history...
82
					$avatar->set($resource);
83
					fclose($resource);
84
				} else {
85
					throw new \Exception('Failed to open old avatar file for reading');
86
				}
87
			} catch (NotFoundException $e) {
88
				// In case there is no avatar we can just skip
89
			} catch (\Throwable $e) {
90
				$this->logger->error('Failed to migrate avatar for user ' . $uid, ['exception' => $e]);
91
			}
92
93
			$counter++;
94
			if ($counter % 100 === 0) {
95
				$this->logger->info('{amount} avatars migrated', ['amount' => $counter]);
96
			}
97
		});
98
	}
99
100
	/**
101
	 * @throws NotFoundException
102
	 */
103
	private function getExtension(string $path): string {
104
		if ($this->owncloudAvatarStorage->file_exists("{$path}/avatar.jpg")) {
105
			return 'jpg';
106
		}
107
		if ($this->owncloudAvatarStorage->file_exists("{$path}/avatar.png")) {
108
			return 'png';
109
		}
110
		throw new NotFoundException("{$path}/avatar.jpg|png");
111
	}
112
113
	protected function buildOwnCloudAvatarPath(string $userId): string {
114
		return substr_replace(substr_replace(md5($userId), '/', 4, 0), '/', 2, 0);
115
	}
116
}
117