diff --git a/apps/files/lib/BackgroundJob/ScanFiles.php b/apps/files/lib/BackgroundJob/ScanFiles.php
index c1ebad0214cf66ef79c93ca65d836111762b831c..a2d35ba9868af5485e1b862ba930b8f12f825822 100644
--- a/apps/files/lib/BackgroundJob/ScanFiles.php
+++ b/apps/files/lib/BackgroundJob/ScanFiles.php
@@ -24,8 +24,8 @@
 namespace OCA\Files\BackgroundJob;
 
 use OC\Files\Utils\Scanner;
+use OCP\EventDispatcher\IEventDispatcher;
 use OCP\IConfig;
-use OCP\IDBConnection;
 use OCP\ILogger;
 use OCP\IUser;
 use OCP\IUserManager;
@@ -41,39 +41,31 @@ class ScanFiles extends \OC\BackgroundJob\TimedJob {
 	private $config;
 	/** @var IUserManager */
 	private $userManager;
-	/** @var IDBConnection */
-	private $dbConnection;
+	/** @var IEventDispatcher */
+	private $dispatcher;
 	/** @var ILogger */
 	private $logger;
+
 	/** Amount of users that should get scanned per execution */
 	const USERS_PER_SESSION = 500;
 
 	/**
 	 * @param IConfig|null $config
 	 * @param IUserManager|null $userManager
-	 * @param IDBConnection|null $dbConnection
+	 * @param IEventDispatcher|null $dispatcher
 	 * @param ILogger|null $logger
 	 */
 	public function __construct(IConfig $config = null,
 								IUserManager $userManager = null,
-								IDBConnection $dbConnection = null,
+								IEventDispatcher $dispatcher = null,
 								ILogger $logger = null) {
 		// Run once per 10 minutes
 		$this->setInterval(60 * 10);
 
-		if (is_null($userManager) || is_null($config)) {
-			$this->fixDIForJobs();
-		} else {
-			$this->config = $config;
-			$this->userManager = $userManager;
-			$this->logger = $logger;
-		}
-	}
-
-	protected function fixDIForJobs() {
-		$this->config = \OC::$server->getConfig();
-		$this->userManager = \OC::$server->getUserManager();
-		$this->logger = \OC::$server->getLogger();
+		$this->config = $config ?? \OC::$server->getConfig();
+		$this->userManager = $userManager ?? \OC::$server->getUserManager();
+		$this->dispatcher = $dispatcher ?? \OC::$server->query(IEventDispatcher::class);
+		$this->logger = $logger ?? \OC::$server->getLogger();
 	}
 
 	/**
@@ -83,7 +75,8 @@ class ScanFiles extends \OC\BackgroundJob\TimedJob {
 		try {
 			$scanner = new Scanner(
 					$user->getUID(),
-					$this->dbConnection,
+					null,
+					$this->dispatcher,
 					$this->logger
 			);
 			$scanner->backgroundScan('');
@@ -101,7 +94,7 @@ class ScanFiles extends \OC\BackgroundJob\TimedJob {
 		if ($this->config->getSystemValueBool('files_no_background_scan', false)) {
 			return;
 		}
-		
+
 		$offset = $this->config->getAppValue('files', 'cronjob_scan_files', 0);
 		$users = $this->userManager->search('', self::USERS_PER_SESSION, $offset);
 		if (!count($users)) {
diff --git a/apps/files/lib/Command/Scan.php b/apps/files/lib/Command/Scan.php
index c0c7ecdb8f04b38faba928ed351edaa56bf6c025..b32e670ffc27034a9d960ff5a2656fcb2b0d8da8 100644
--- a/apps/files/lib/Command/Scan.php
+++ b/apps/files/lib/Command/Scan.php
@@ -36,6 +36,7 @@ use Doctrine\DBAL\Connection;
 use OC\Core\Command\Base;
 use OC\Core\Command\InterruptedException;
 use OC\ForbiddenException;
+use OCP\EventDispatcher\IEventDispatcher;
 use OCP\Files\Mount\IMountPoint;
 use OCP\Files\NotFoundException;
 use OCP\Files\StorageNotAvailableException;
@@ -114,7 +115,7 @@ class Scan extends Base {
 
 	protected function scanFiles($user, $path, OutputInterface $output, $backgroundScan = false, $recursive = true, $homeOnly = false) {
 		$connection = $this->reconnectToDatabase($output);
-		$scanner = new \OC\Files\Utils\Scanner($user, $connection, \OC::$server->getLogger());
+		$scanner = new \OC\Files\Utils\Scanner($user, $connection, \OC::$server->query(IEventDispatcher::class), \OC::$server->getLogger());
 
 		# check on each file/folder if there was a user interrupt (ctrl-c) and throw an exception
 
diff --git a/apps/files/lib/Command/ScanAppData.php b/apps/files/lib/Command/ScanAppData.php
index c8609b57b737f70353f47131e40dab9ba3725a4e..38d6ed2d425266a877ba713df24aeffaedc99a57 100644
--- a/apps/files/lib/Command/ScanAppData.php
+++ b/apps/files/lib/Command/ScanAppData.php
@@ -30,6 +30,7 @@ use Doctrine\DBAL\Connection;
 use OC\Core\Command\Base;
 use OC\Core\Command\InterruptedException;
 use OC\ForbiddenException;
+use OCP\EventDispatcher\IEventDispatcher;
 use OCP\Files\IRootFolder;
 use OCP\Files\NotFoundException;
 use OCP\Files\StorageNotAvailableException;
@@ -85,7 +86,7 @@ class ScanAppData extends Base {
 		}
 
 		$connection = $this->reconnectToDatabase($output);
-		$scanner = new \OC\Files\Utils\Scanner(null, $connection, \OC::$server->getLogger());
+		$scanner = new \OC\Files\Utils\Scanner(null, $connection, \OC::$server->query(IEventDispatcher::class), \OC::$server->getLogger());
 
 		# check on each file/folder if there was a user interrupt (ctrl-c) and throw an exception
 		$scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', function ($path) use ($output) {
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 016b3c360efab4260ed49b1aaf131840431791c3..36d9f0c88731109fef5cdf34498d197f8f3fd3b0 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -220,6 +220,13 @@ return array(
     'OCP\\Files\\Config\\IUserMountCache' => $baseDir . '/lib/public/Files/Config/IUserMountCache.php',
     'OCP\\Files\\EmptyFileNameException' => $baseDir . '/lib/public/Files/EmptyFileNameException.php',
     'OCP\\Files\\EntityTooLargeException' => $baseDir . '/lib/public/Files/EntityTooLargeException.php',
+    'OCP\\Files\\Events\\BeforeFileScannedEvent' => $baseDir . '/lib/public/Files/Events/BeforeFileScannedEvent.php',
+    'OCP\\Files\\Events\\BeforeFolderScannedEvent' => $baseDir . '/lib/public/Files/Events/BeforeFolderScannedEvent.php',
+    'OCP\\Files\\Events\\FileCacheUpdated' => $baseDir . '/lib/public/Files/Events/FileCacheUpdated.php',
+    'OCP\\Files\\Events\\FileScannedEvent' => $baseDir . '/lib/public/Files/Events/FileScannedEvent.php',
+    'OCP\\Files\\Events\\FolderScannedEvent' => $baseDir . '/lib/public/Files/Events/FolderScannedEvent.php',
+    'OCP\\Files\\Events\\NodeAddedToCache' => $baseDir . '/lib/public/Files/Events/NodeAddedToCache.php',
+    'OCP\\Files\\Events\\NodeRemovedFromCache' => $baseDir . '/lib/public/Files/Events/NodeRemovedFromCache.php',
     'OCP\\Files\\File' => $baseDir . '/lib/public/Files/File.php',
     'OCP\\Files\\FileInfo' => $baseDir . '/lib/public/Files/FileInfo.php',
     'OCP\\Files\\FileNameTooLongException' => $baseDir . '/lib/public/Files/FileNameTooLongException.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 5d63c7740eb7066e100406a238d5aa2eb085bf0e..a2c28db3e60547b413df8fe97c094aaf879634c4 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -249,6 +249,13 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
         'OCP\\Files\\Config\\IUserMountCache' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IUserMountCache.php',
         'OCP\\Files\\EmptyFileNameException' => __DIR__ . '/../../..' . '/lib/public/Files/EmptyFileNameException.php',
         'OCP\\Files\\EntityTooLargeException' => __DIR__ . '/../../..' . '/lib/public/Files/EntityTooLargeException.php',
+        'OCP\\Files\\Events\\BeforeFileScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/BeforeFileScannedEvent.php',
+        'OCP\\Files\\Events\\BeforeFolderScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/BeforeFolderScannedEvent.php',
+        'OCP\\Files\\Events\\FileCacheUpdated' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FileCacheUpdated.php',
+        'OCP\\Files\\Events\\FileScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FileScannedEvent.php',
+        'OCP\\Files\\Events\\FolderScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FolderScannedEvent.php',
+        'OCP\\Files\\Events\\NodeAddedToCache' => __DIR__ . '/../../..' . '/lib/public/Files/Events/NodeAddedToCache.php',
+        'OCP\\Files\\Events\\NodeRemovedFromCache' => __DIR__ . '/../../..' . '/lib/public/Files/Events/NodeRemovedFromCache.php',
         'OCP\\Files\\File' => __DIR__ . '/../../..' . '/lib/public/Files/File.php',
         'OCP\\Files\\FileInfo' => __DIR__ . '/../../..' . '/lib/public/Files/FileInfo.php',
         'OCP\\Files\\FileNameTooLongException' => __DIR__ . '/../../..' . '/lib/public/Files/FileNameTooLongException.php',
diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php
index 45194b57cbfd62adbf8ecebb32da5f6c29b85706..53712d28171e13e2d11ea1ee030406175648d439 100644
--- a/lib/private/Files/Utils/Scanner.php
+++ b/lib/private/Files/Utils/Scanner.php
@@ -36,9 +36,18 @@ use OC\ForbiddenException;
 use OC\Hooks\PublicEmitter;
 use OC\Lock\DBLockingProvider;
 use OCA\Files_Sharing\SharedStorage;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Events\BeforeFileScannedEvent;
+use OCP\Files\Events\BeforeFolderScannedEvent;
+use OCP\Files\Events\NodeAddedToCache;
+use OCP\Files\Events\FileCacheUpdated;
+use OCP\Files\Events\NodeRemovedFromCache;
+use OCP\Files\Events\FileScannedEvent;
+use OCP\Files\Events\FolderScannedEvent;
 use OCP\Files\NotFoundException;
 use OCP\Files\Storage\IStorage;
 use OCP\Files\StorageNotAvailableException;
+use OCP\IDBConnection;
 use OCP\ILogger;
 
 /**
@@ -53,19 +62,16 @@ use OCP\ILogger;
 class Scanner extends PublicEmitter {
 	const MAX_ENTRIES_TO_COMMIT = 10000;
 
-	/**
-	 * @var string $user
-	 */
+	/** @var string $user */
 	private $user;
 
-	/**
-	 * @var \OCP\IDBConnection
-	 */
+	/** @var IDBConnection */
 	protected $db;
 
-	/**
-	 * @var ILogger
-	 */
+	/** @var IEventDispatcher */
+	private $dispatcher;
+
+	/** @var ILogger */
 	protected $logger;
 
 	/**
@@ -84,13 +90,15 @@ class Scanner extends PublicEmitter {
 
 	/**
 	 * @param string $user
-	 * @param \OCP\IDBConnection $db
+	 * @param IDBConnection|null $db
+	 * @param IEventDispatcher $dispatcher
 	 * @param ILogger $logger
 	 */
-	public function __construct($user, $db, ILogger $logger) {
-		$this->logger = $logger;
+	public function __construct($user, $db, IEventDispatcher $dispatcher, ILogger $logger) {
 		$this->user = $user;
 		$this->db = $db;
+		$this->dispatcher = $dispatcher;
+		$this->logger = $logger;
 		// when DB locking is used, no DB transactions will be used
 		$this->useTransaction = !(\OC::$server->getLockingProvider() instanceof DBLockingProvider);
 	}
@@ -121,18 +129,21 @@ class Scanner extends PublicEmitter {
 	 */
 	protected function attachListener($mount) {
 		$scanner = $mount->getStorage()->getScanner();
-		$emitter = $this;
-		$scanner->listen('\OC\Files\Cache\Scanner', 'scanFile', function ($path) use ($mount, $emitter) {
-			$emitter->emit('\OC\Files\Utils\Scanner', 'scanFile', array($mount->getMountPoint() . $path));
+		$scanner->listen('\OC\Files\Cache\Scanner', 'scanFile', function ($path) use ($mount) {
+			$this->emit('\OC\Files\Utils\Scanner', 'scanFile', array($mount->getMountPoint() . $path));
+			$this->dispatcher->dispatchTyped(new BeforeFileScannedEvent($mount->getMountPoint() . $path));
 		});
-		$scanner->listen('\OC\Files\Cache\Scanner', 'scanFolder', function ($path) use ($mount, $emitter) {
-			$emitter->emit('\OC\Files\Utils\Scanner', 'scanFolder', array($mount->getMountPoint() . $path));
+		$scanner->listen('\OC\Files\Cache\Scanner', 'scanFolder', function ($path) use ($mount) {
+			$this->emit('\OC\Files\Utils\Scanner', 'scanFolder', array($mount->getMountPoint() . $path));
+			$this->dispatcher->dispatchTyped(new BeforeFolderScannedEvent($mount->getMountPoint() . $path));
 		});
-		$scanner->listen('\OC\Files\Cache\Scanner', 'postScanFile', function ($path) use ($mount, $emitter) {
-			$emitter->emit('\OC\Files\Utils\Scanner', 'postScanFile', array($mount->getMountPoint() . $path));
+		$scanner->listen('\OC\Files\Cache\Scanner', 'postScanFile', function ($path) use ($mount) {
+			$this->emit('\OC\Files\Utils\Scanner', 'postScanFile', array($mount->getMountPoint() . $path));
+			$this->dispatcher->dispatchTyped(new FileScannedEvent($mount->getMountPoint() . $path));
 		});
-		$scanner->listen('\OC\Files\Cache\Scanner', 'postScanFolder', function ($path) use ($mount, $emitter) {
-			$emitter->emit('\OC\Files\Utils\Scanner', 'postScanFolder', array($mount->getMountPoint() . $path));
+		$scanner->listen('\OC\Files\Cache\Scanner', 'postScanFolder', function ($path) use ($mount) {
+			$this->emit('\OC\Files\Utils\Scanner', 'postScanFolder', array($mount->getMountPoint() . $path));
+			$this->dispatcher->dispatchTyped(new FolderScannedEvent($mount->getMountPoint() . $path));
 		});
 	}
 
@@ -225,12 +236,15 @@ class Scanner extends PublicEmitter {
 
 			$scanner->listen('\OC\Files\Cache\Scanner', 'removeFromCache', function ($path) use ($storage) {
 				$this->postProcessEntry($storage, $path);
+				$this->dispatcher->dispatchTyped(new NodeRemovedFromCache($storage, $path));
 			});
 			$scanner->listen('\OC\Files\Cache\Scanner', 'updateCache', function ($path) use ($storage) {
 				$this->postProcessEntry($storage, $path);
+				$this->dispatcher->dispatchTyped(new FileCacheUpdated($storage, $path));
 			});
 			$scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', function ($path) use ($storage) {
 				$this->postProcessEntry($storage, $path);
+				$this->dispatcher->dispatchTyped(new NodeAddedToCache($storage, $path));
 			});
 
 			if (!$storage->file_exists($relativePath)) {
diff --git a/lib/public/Files/Events/BeforeFileScannedEvent.php b/lib/public/Files/Events/BeforeFileScannedEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f8dca2b33326d3ccc466305de551171518e66c7
--- /dev/null
+++ b/lib/public/Files/Events/BeforeFileScannedEvent.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * @since 18.0.0
+ */
+class BeforeFileScannedEvent extends Event {
+
+	/** @var string */
+	private $absolutePath;
+
+	/**
+	 * @param string $absolutePath
+	 *
+	 * @since 18.0.0
+	 */
+	public function __construct(string $absolutePath) {
+		parent::__construct();
+		$this->absolutePath = $absolutePath;
+	}
+
+	/**
+	 * @return string
+	 * @since 18.0.0
+	 */
+	public function getAbsolutePath(): string {
+		return $this->absolutePath;
+	}
+
+}
diff --git a/lib/public/Files/Events/BeforeFolderScannedEvent.php b/lib/public/Files/Events/BeforeFolderScannedEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..a253974c21ec9c662f667628b052f4652b5691e0
--- /dev/null
+++ b/lib/public/Files/Events/BeforeFolderScannedEvent.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * @since 18.0.0
+ */
+class BeforeFolderScannedEvent extends Event {
+
+	/** @var string */
+	private $absolutePath;
+
+	/**
+	 * @param string $absolutePath
+	 *
+	 * @since 18.0.0
+	 */
+	public function __construct(string $absolutePath) {
+		parent::__construct();
+		$this->absolutePath = $absolutePath;
+	}
+
+	/**
+	 * @return string
+	 * @since 18.0.0
+	 */
+	public function getAbsolutePath(): string {
+		return $this->absolutePath;
+	}
+
+}
diff --git a/lib/public/Files/Events/FileCacheUpdated.php b/lib/public/Files/Events/FileCacheUpdated.php
new file mode 100644
index 0000000000000000000000000000000000000000..c0f4771ae520923c6f8bd380fdf8d3081b71ff23
--- /dev/null
+++ b/lib/public/Files/Events/FileCacheUpdated.php
@@ -0,0 +1,70 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+use OCP\Files\Storage\IStorage;
+
+/**
+ * @since 18.0.0
+ */
+class FileCacheUpdated extends Event {
+
+	/** @var IStorage */
+	private $storage;
+
+	/** @var string */
+	private $path;
+
+	/**
+	 * @param IStorage $storage
+	 * @param string $path
+	 * @since 18.0.0
+	 */
+	public function __construct(IStorage $storage,
+								string $path) {
+		parent::__construct();
+		$this->storage = $storage;
+		$this->path = $path;
+	}
+
+	/**
+	 * @return IStorage
+	 * @since 18.0.0
+	 */
+	public function getStorage(): IStorage {
+		return $this->storage;
+	}
+
+	/**
+	 * @return string
+	 * @since 18.0.0
+	 */
+	public function getPath(): string {
+		return $this->path;
+	}
+
+}
diff --git a/lib/public/Files/Events/FileScannedEvent.php b/lib/public/Files/Events/FileScannedEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..a93189225e4c6fa814206d3d1610510add4fb97b
--- /dev/null
+++ b/lib/public/Files/Events/FileScannedEvent.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * @since 18.0.0
+ */
+class FileScannedEvent extends Event {
+
+	/** @var string */
+	private $absolutePath;
+
+	/**
+	 * @param string $absolutePath
+	 *
+	 * @since 18.0.0
+	 */
+	public function __construct(string $absolutePath) {
+		parent::__construct();
+		$this->absolutePath = $absolutePath;
+	}
+
+	/**
+	 * @return string
+	 * @since 18.0.0
+	 */
+	public function getAbsolutePath(): string {
+		return $this->absolutePath;
+	}
+
+}
diff --git a/lib/public/Files/Events/FolderScannedEvent.php b/lib/public/Files/Events/FolderScannedEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1667cd8bc694800046dfd96bc8ca90bf5f56e50
--- /dev/null
+++ b/lib/public/Files/Events/FolderScannedEvent.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * @since 18.0.0
+ */
+class FolderScannedEvent extends Event {
+
+	/** @var string */
+	private $absolutePath;
+
+	/**
+	 * @param string $absolutePath
+	 *
+	 * @since 18.0.0
+	 */
+	public function __construct(string $absolutePath) {
+		parent::__construct();
+		$this->absolutePath = $absolutePath;
+	}
+
+	/**
+	 * @return string
+	 * @since 18.0.0
+	 */
+	public function getAbsolutePath(): string {
+		return $this->absolutePath;
+	}
+
+}
diff --git a/lib/public/Files/Events/NodeAddedToCache.php b/lib/public/Files/Events/NodeAddedToCache.php
new file mode 100644
index 0000000000000000000000000000000000000000..966d42a384ea2b6c5cc47ec42fa9c3672f8d7255
--- /dev/null
+++ b/lib/public/Files/Events/NodeAddedToCache.php
@@ -0,0 +1,70 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+use OCP\Files\Storage\IStorage;
+
+/**
+ * @since 18.0.0
+ */
+class NodeAddedToCache extends Event {
+
+	/** @var IStorage */
+	private $storage;
+
+	/** @var string */
+	private $path;
+
+	/**
+	 * @param IStorage $storage
+	 * @param string $path
+	 * @since 18.0.0
+	 */
+	public function __construct(IStorage $storage,
+								string $path) {
+		parent::__construct();
+		$this->storage = $storage;
+		$this->path = $path;
+	}
+
+	/**
+	 * @return IStorage
+	 * @since 18.0.0
+	 */
+	public function getStorage(): IStorage {
+		return $this->storage;
+	}
+
+	/**
+	 * @return string
+	 * @since 18.0.0
+	 */
+	public function getPath(): string {
+		return $this->path;
+	}
+
+}
diff --git a/lib/public/Files/Events/NodeRemovedFromCache.php b/lib/public/Files/Events/NodeRemovedFromCache.php
new file mode 100644
index 0000000000000000000000000000000000000000..c8d84624a8b3a0f469dd7c3cc0c66d2b46a2235d
--- /dev/null
+++ b/lib/public/Files/Events/NodeRemovedFromCache.php
@@ -0,0 +1,70 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+use OCP\Files\Storage\IStorage;
+
+/**
+ * @since 18.0.0
+ */
+class NodeRemovedFromCache extends Event {
+
+	/** @var IStorage */
+	private $storage;
+
+	/** @var string */
+	private $path;
+
+	/**
+	 * @param IStorage $storage
+	 * @param string $path
+	 * @since 18.0.0
+	 */
+	public function __construct(IStorage $storage,
+								string $path) {
+		parent::__construct();
+		$this->storage = $storage;
+		$this->path = $path;
+	}
+
+	/**
+	 * @return IStorage
+	 * @since 18.0.0
+	 */
+	public function getStorage(): IStorage {
+		return $this->storage;
+	}
+
+	/**
+	 * @return string
+	 * @since 18.0.0
+	 */
+	public function getPath(): string {
+		return $this->path;
+	}
+
+}
diff --git a/tests/lib/Files/EtagTest.php b/tests/lib/Files/EtagTest.php
index 554812253f3117cbc04d94bd18803ef3b2cfd492..d3b372fe1376245d79eb4af9bf66b62e7e7c21b6 100644
--- a/tests/lib/Files/EtagTest.php
+++ b/tests/lib/Files/EtagTest.php
@@ -9,6 +9,7 @@
 namespace Test\Files;
 
 use OC\Files\Filesystem;
+use OCP\EventDispatcher\IEventDispatcher;
 use OCP\Share;
 use OCA\Files_Sharing\AppInfo\Application;
 
@@ -35,7 +36,7 @@ class EtagTest extends \Test\TestCase {
 		\OC_Hook::clear('OC_Filesystem', 'setup');
 		// init files sharing
 		new Application();
-		
+
 		\OC\Share\Share::registerBackend('file', 'OCA\Files_Sharing\ShareBackend\File');
 		\OC\Share\Share::registerBackend('folder', 'OCA\Files_Sharing\ShareBackend\Folder', 'file');
 
@@ -69,7 +70,7 @@ class EtagTest extends \Test\TestCase {
 		$files = array('/foo.txt', '/folder/bar.txt', '/folder/subfolder', '/folder/subfolder/qwerty.txt');
 		$originalEtags = $this->getEtags($files);
 
-		$scanner = new \OC\Files\Utils\Scanner($user1, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new \OC\Files\Utils\Scanner($user1, \OC::$server->getDatabaseConnection(), \OC::$server->query(IEventDispatcher::class), \OC::$server->getLogger());
 		$scanner->backgroundScan('/');
 
 		$newEtags = $this->getEtags($files);
diff --git a/tests/lib/Files/Utils/ScannerTest.php b/tests/lib/Files/Utils/ScannerTest.php
index 4af252735f68b010b0224d852e8488293b312c1e..44422cd97d131ce25091b6b232294fb939bb3ad0 100644
--- a/tests/lib/Files/Utils/ScannerTest.php
+++ b/tests/lib/Files/Utils/ScannerTest.php
@@ -12,6 +12,7 @@ use OC\Files\Filesystem;
 use OC\Files\Mount\MountPoint;
 use OC\Files\Storage\Temporary;
 use OCA\Files_Sharing\SharedStorage;
+use OCP\EventDispatcher\IEventDispatcher;
 use OCP\Files\Config\IMountProvider;
 use OCP\Files\Storage\IStorageFactory;
 use OCP\IUser;
@@ -71,7 +72,7 @@ class ScannerTest extends \Test\TestCase {
 		$storage->file_put_contents('foo.txt', 'qwerty');
 		$storage->file_put_contents('folder/bar.txt', 'qwerty');
 
-		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->getLogger());
 		$scanner->addMount($mount);
 
 		$scanner->scan('');
@@ -93,7 +94,7 @@ class ScannerTest extends \Test\TestCase {
 		$storage->file_put_contents('foo.txt', 'qwerty');
 		$storage->file_put_contents('folder/bar.txt', 'qwerty');
 
-		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->getLogger());
 		$scanner->addMount($mount);
 
 		$scanner->scan('');
@@ -131,7 +132,7 @@ class ScannerTest extends \Test\TestCase {
 		$storage->file_put_contents('foo.txt', 'qwerty');
 		$storage->file_put_contents('folder/bar.txt', 'qwerty');
 
-		$scanner = new \OC\Files\Utils\Scanner($uid, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new \OC\Files\Utils\Scanner($uid, \OC::$server->getDatabaseConnection(), \OC::$server->query(IEventDispatcher::class), \OC::$server->getLogger());
 
 		$this->assertFalse($cache->inCache('folder/bar.txt'));
 		$scanner->scan('/' . $uid . '/files/foo');
@@ -163,7 +164,7 @@ class ScannerTest extends \Test\TestCase {
 		$this->expectException(\InvalidArgumentException::class);
 		$this->expectExceptionMessage('Invalid path to scan');
 
-		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->getLogger());
 		$scanner->scan($invalidPath);
 	}
 
@@ -177,7 +178,7 @@ class ScannerTest extends \Test\TestCase {
 		$storage->file_put_contents('folder/bar.txt', 'qwerty');
 		$storage->touch('folder/bar.txt', time() - 200);
 
-		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->getLogger());
 		$scanner->addMount($mount);
 
 		$scanner->scan('');
@@ -204,7 +205,7 @@ class ScannerTest extends \Test\TestCase {
 		$sharedStorage->expects($this->never())
 			->method('getScanner');
 
-		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->getLogger());
 		$scanner->addMount($sharedMount);
 		$scanner->scan('');
 
@@ -223,7 +224,7 @@ class ScannerTest extends \Test\TestCase {
 		$storage->file_put_contents('folder/bar.txt', 'qwerty');
 		$storage->file_put_contents('folder/subfolder/foobar.txt', 'qwerty');
 
-		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+		$scanner = new TestScanner('', \OC::$server->getDatabaseConnection(), $this->createMock(IEventDispatcher::class), \OC::$server->getLogger());
 		$scanner->addMount($mount);
 
 		$scanner->scan('', $recusive = false);