Passed
Push — master ( 022c2a...9c43c9 )
by Pauli
02:58
created

FileHooks::preRenamed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Morris Jobke <[email protected]>
10
 * @author Pauli Järvinen <[email protected]>
11
 * @copyright Morris Jobke 2014
12
 * @copyright Pauli Järvinen 2017 - 2024
13
 */
14
15
namespace OCA\Music\Hooks;
16
17
use OCP\AppFramework\IAppContainer;
18
use OCP\Files\FileInfo;
19
use OCP\Files\Node;
20
21
use OCA\Music\AppInfo\Application;;
22
23
class FileHooks {
24
	private $filesystemRoot;
25
26
	public function __construct($filesystemRoot) {
27
		$this->filesystemRoot = $filesystemRoot;
28
	}
29
30
	/**
31
	 * Invoke auto update of music database after file or folder deletion
32
	 * @param Node $node pointing to the file or folder
33
	 */
34
	public static function deleted(Node $node) : void {
35
		$container = self::getContainer();
36
		$scanner = $container->query('Scanner');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

36
		$scanner = /** @scrutinizer ignore-deprecated */ $container->query('Scanner');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
37
38
		if ($node->getType() == FileInfo::TYPE_FILE) {
39
			$scanner->delete($node->getId());
40
		} else {
41
			$scanner->deleteFolder($node);
42
		}
43
	}
44
45
	/**
46
	 * Invoke auto update of music database after file update or file creation
47
	 * @param Node $node pointing to the file
48
	 */
49
	public static function updated(Node $node) : void {
50
		// At least on Nextcloud 13, it sometimes happens that this hook is triggered
51
		// when the core creates some temporary file and trying to access the provided
52
		// node throws an exception, probably because the temp file is already removed
53
		// by the time the execution gets here. See #636.
54
		// Furthermore, when the core opens a file in stream mode for writing using
55
		// File::fopen, this hook gets triggered immediately after the opening succeeds,
56
		// before anything is actually written and while the file is *exclusively locked
57
		// because of the write mode*. See #638.
58
		$container = self::getContainer();
59
		try {
60
			self::handleUpdated($node, $container);
61
		} catch (\OCP\Files\NotFoundException $e) {
62
			$logger = $container->query('Logger');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

62
			$logger = /** @scrutinizer ignore-deprecated */ $container->query('Logger');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
63
			$logger->log('FileHooks::updated triggered for a non-existing file', 'warn');
64
		} catch (\OCP\Lock\LockedException $e) {
65
			$logger = $container->query('Logger');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

65
			$logger = /** @scrutinizer ignore-deprecated */ $container->query('Logger');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
66
			$logger->log('FileHooks::updated triggered for a locked file ' . $node->getName(), 'warn');
67
		}
68
	}
69
70
	private static function handleUpdated(Node $node, IAppContainer $container) : void {
71
		// we are interested only about updates on files, not on folders
72
		if ($node->getType() == FileInfo::TYPE_FILE) {
73
			$scanner = $container->query('Scanner');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

73
			$scanner = /** @scrutinizer ignore-deprecated */ $container->query('Scanner');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
74
			$userId = self::getUser($node, $container);
75
76
			// Ignore event if we got no user or folder or the user has not yet scanned the music
77
			// collection. The last condition is especially to prevent problems when creating new user
78
			// and the default file set contains one or more audio files (see the discussion in #638).
79
			if (!empty($userId) && self::userHasMusicLib($userId, $container)) {
80
				$scanner->update($node, $userId, $node->getPath());
81
			}
82
		}
83
	}
84
85
	private static function moved(Node $node) : void {
86
		$container = self::getContainer();
87
		try {
88
			self::handleMoved($node, $container);
89
		} catch (\OCP\Files\NotFoundException $e) {
90
			$logger = $container->query('Logger');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

90
			$logger = /** @scrutinizer ignore-deprecated */ $container->query('Logger');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
91
			$logger->log('FileHooks::moved triggered for a non-existing file', 'warn');
92
		} catch (\OCP\Lock\LockedException $e) {
93
			$logger = $container->query('Logger');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

93
			$logger = /** @scrutinizer ignore-deprecated */ $container->query('Logger');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
94
			$logger->log('FileHooks::moved triggered for a locked file ' . $node->getName(), 'warn');
95
		}
96
	}
97
98
	private static function handleMoved(Node $node, IAppContainer $container) : void {
99
		$scanner = $container->query('Scanner');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

99
		$scanner = /** @scrutinizer ignore-deprecated */ $container->query('Scanner');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
100
		$userId = self::getUser($node, $container);
101
102
		if (!empty($userId) && self::userHasMusicLib($userId, $container)) {
103
			if ($node->getType() == FileInfo::TYPE_FILE) {
104
				$scanner->fileMoved($node, $userId);
105
			} else {
106
				$scanner->folderMoved($node, $userId);
107
			}
108
		}
109
	}
110
111
	private static function getUser(Node $node, IAppContainer $container) : ?string {
112
		$userId = $container->query('UserId');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

112
		$userId = /** @scrutinizer ignore-deprecated */ $container->query('UserId');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
113
114
		// When a file is uploaded to a folder shared by link, we end up here without current user.
115
		// In that case, fall back to using file owner
116
		if (empty($userId)) {
117
			// At least some versions of NC may violate their PhpDoc and return null owner, hence we need to aid PHPStan a bit about the type.
118
			/** @var \OCP\IUser|null $owner */
119
			$owner = $node->getOwner();
120
			$userId = $owner ? $owner->getUID() : null;
0 ignored issues
show
introduced by
$owner is of type OCP\IUser, thus it always evaluated to true.
Loading history...
121
		}
122
123
		return $userId;
124
	}
125
126
	private static function getContainer() : IAppContainer {
127
		$app = \OC::$server->query(Application::class);
128
		return $app->getContainer();
129
	}
130
131
	/**
132
	 * Check if user has any scanned tracks in his/her music library
133
	 * @param string $userId
134
	 * @param IAppContainer $container
135
	 */
136
	private static function userHasMusicLib(string $userId, IAppContainer $container) : bool {
137
		$trackBusinessLayer = $container->query('TrackBusinessLayer');
0 ignored issues
show
Deprecated Code introduced by
The function OCP\IContainer::query() has been deprecated: 20.0.0 use \Psr\Container\ContainerInterface::get ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

137
		$trackBusinessLayer = /** @scrutinizer ignore-deprecated */ $container->query('TrackBusinessLayer');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
138
		return 0 < $trackBusinessLayer->count($userId);
139
	}
140
141
	public static function postRenamed(Node $source, Node $target) : void {
142
		// Beware: the $source describes the past state of the file and some of its functions will throw upon calling
143
144
		if ($source->getParent()->getId() != $target->getParent()->getId()) {
145
			self::moved($target);
146
		} else {
147
			self::updated($target);
148
		}
149
	}
150
151
	public function register() {
152
		$this->filesystemRoot->listen('\OC\Files', 'postWrite', [__CLASS__, 'updated']);
153
		$this->filesystemRoot->listen('\OC\Files', 'preDelete', [__CLASS__, 'deleted']);
154
		$this->filesystemRoot->listen('\OC\Files', 'postRename', [__CLASS__, 'postRenamed']);
155
	}
156
}
157