diff options
Diffstat (limited to 'lib')
22 files changed, 256 insertions, 72 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 0ff46de07de..5cedef83c61 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -61,6 +61,7 @@ return array( 'OCP\\Comments\\CommentsEntityEvent' => $baseDir . '/lib/public/Comments/CommentsEntityEvent.php', 'OCP\\Comments\\CommentsEvent' => $baseDir . '/lib/public/Comments/CommentsEvent.php', 'OCP\\Comments\\IComment' => $baseDir . '/lib/public/Comments/IComment.php', + 'OCP\\Comments\\ICommentsEventHandler' => $baseDir . '/lib/public/Comments/ICommentsEventHandler.php', 'OCP\\Comments\\ICommentsManager' => $baseDir . '/lib/public/Comments/ICommentsManager.php', 'OCP\\Comments\\ICommentsManagerFactory' => $baseDir . '/lib/public/Comments/ICommentsManagerFactory.php', 'OCP\\Comments\\IllegalIDChangeException' => $baseDir . '/lib/public/Comments/IllegalIDChangeException.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 24058a22edb..bce3916c8a0 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -91,6 +91,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Comments\\CommentsEntityEvent' => __DIR__ . '/../../..' . '/lib/public/Comments/CommentsEntityEvent.php', 'OCP\\Comments\\CommentsEvent' => __DIR__ . '/../../..' . '/lib/public/Comments/CommentsEvent.php', 'OCP\\Comments\\IComment' => __DIR__ . '/../../..' . '/lib/public/Comments/IComment.php', + 'OCP\\Comments\\ICommentsEventHandler' => __DIR__ . '/../../..' . '/lib/public/Comments/ICommentsEventHandler.php', 'OCP\\Comments\\ICommentsManager' => __DIR__ . '/../../..' . '/lib/public/Comments/ICommentsManager.php', 'OCP\\Comments\\ICommentsManagerFactory' => __DIR__ . '/../../..' . '/lib/public/Comments/ICommentsManagerFactory.php', 'OCP\\Comments\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Comments/IllegalIDChangeException.php', diff --git a/lib/l10n/fi_FI.js b/lib/l10n/fi_FI.js index 1b149a51d9b..9ef48947914 100644 --- a/lib/l10n/fi_FI.js +++ b/lib/l10n/fi_FI.js @@ -6,6 +6,7 @@ OC.L10N.register( "See %s" : "Katso %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Tämän voi yleensä korjata antamalla %shttp-palvelimelle kirjoitusoikeuden asetushakemistoon%s.", "Sample configuration detected" : "Esimerkkimääritykset havaittu", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "On havaittu, että esimerkkimäärityksen on kopioitu. Se voi rikkoa asennuksesi, eikä sitä tueta. Lue ohjeet ennen kuin muutat config.php tiedostoa.", "PHP %s or higher is required." : "PHP %s tai sitä uudempi vaaditaan.", "PHP with a version lower than %s is required." : "PHP versiota %s alempi tarvitaan.", "%sbit or higher PHP required." : "%s-bit tai korkeampi PHP vaaditaan.", @@ -15,6 +16,8 @@ OC.L10N.register( "Library %s with a version higher than %s is required - available version %s." : "Kirjasto %s versiota %s tai uudempi vaaditaan - käytettävissä oleva versio %s.", "Library %s with a version lower than %s is required - available version %s." : "Kirjasto %s versiota alempi %s tarvitaan - käytettävissä oleva versio %s.", "Following platforms are supported: %s" : "Seuraavat alustat ovat tuettuja: %s", + "Server version %s or higher is required." : "Palvelinversio %s tai sitä uudempi vaaditaan.", + "Server version %s or lower is required." : "Palvelinversio %s tai alhaisempi vaaditaan.", "Unknown filetype" : "Tuntematon tiedostotyyppi", "Invalid image" : "Virheellinen kuva", "today" : "tänään", @@ -31,6 +34,7 @@ OC.L10N.register( "Empty filename is not allowed" : "Tiedostonimi ei voi olla tyhjä", "Dot files are not allowed" : "Pistetiedostot eivät ole sallittuja", "4-byte characters are not supported in file names" : "4 tavun merkit eivät ole tuettuja tiedostojen nimissä", + "File name is a reserved word" : "Tiedoston nimi on varattu sana", "File name contains at least one invalid character" : "Tiedoston nimi sisältää ainakin yhden virheellisen merkin", "File name is too long" : "Tiedoston nimi on liian pitkä", "App directory already exists" : "Sovelluskansio on jo olemassa", @@ -45,6 +49,8 @@ OC.L10N.register( "App cannot be installed because appinfo file cannot be read." : "Sovellusta ei voi asentaa, koska appinfo-tiedostoa ei voi lukea.", "Signature could not get checked. Please contact the app developer and check your admin screen." : "Allekirjoituksen tarkistaminen ei onnistunut. Ota yhteys sovelluskehittäjään ja tarkista ylläpitonäkymä.", "App can't be installed because of not allowed code in the App" : "Sovellusta ei voi asentaa, koska sovellus sisältää kiellettyä koodia", + "App can't be installed because it is not compatible with this version of the server" : "Sovelluksen asennus ei onnistu, koska se ei ole yhteensopiva tämän palvelinversion kanssa.", + "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Sovelluksen asennus ei onnistu, koska se sisältää <shipped>true</shipped> tunnisteen, jota ei sallita sovelluksille, joita ei toimiteta Nextcloudin mukana.", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Sovelluksen asennus ei onnistu, koska sen info.xml:ssä ilmoitettu versio ei ole sama kuin sovelluskaupassa ilmoitettu versio", "APCu" : "APCu", "Redis" : "Redis", @@ -54,6 +60,7 @@ OC.L10N.register( "Logging" : "Loki", "Additional settings" : "Lisäasetukset", "Tips & tricks" : "Vinkkejä", + "%s enter the database username and name." : "%s anna tietokannan käyttäjätunnus ja nimi.", "%s enter the database username." : "%s anna tietokannan käyttäjätunnus.", "%s enter the database name." : "%s anna tietokannan nimi.", "%s you may not use dots in the database name" : "%s et voi käyttää pisteitä tietokannan nimessä", @@ -61,6 +68,7 @@ OC.L10N.register( "Oracle username and/or password not valid" : "Oraclen käyttäjätunnus ja/tai salasana on väärin", "DB Error: \"%s\"" : "Tietokantavirhe: \"%s\"", "Offending command was: \"%s\"" : "Loukkaava komento oli: \"%s\"", + "You need to enter either an existing account or the administrator." : "Sinun täytyy antaa joko olemassa oleva tili tai ylläpitäjä.", "Offending command was: \"%s\", name: %s, password: %s" : "Loukkaava komento oli: \"%s\", nimi: %s, salasana: %s", "PostgreSQL username and/or password not valid" : "PostgreSQL:n käyttäjätunnus ja/tai salasana on väärin", "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ei ole tuettu, joten %s ei toimi kunnolla tällä alustalla. Käytä omalla vastuulla!", @@ -69,8 +77,10 @@ OC.L10N.register( "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Poista open_basedir-asetus php.ini-tiedostosta tai vaihda 64-bittiseen PHP:hen.", "Set an admin username." : "Aseta ylläpitäjän käyttäjätunnus.", "Set an admin password." : "Aseta ylläpitäjän salasana.", + "Can't create or write into the data directory %s" : "Ei voi luoda tai kirjoittaa data -hakemistoon %s", "Invalid Federated Cloud ID" : "Virheellinen federoidun pilven tunniste", "%s shared »%s« with you" : "%s jakoi kohteen »%s« kanssasi", + "Sharing %s failed, because the backend does not allow shares from type %i" : "Kohteen %s jakaminen epäonnistui, koska tietovarasto ei salli %i tyyppisiä jakoja", "Sharing %s failed, because the file does not exist" : "Kohteen %s jakaminen epäonnistui, koska tiedostoa ei ole olemassa", "You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.", "Sharing %s failed, because you can not share with yourself" : "Kohteen %s jakaminen epäonnistui, koska et voi jakaa itsesi kanssa", diff --git a/lib/l10n/fi_FI.json b/lib/l10n/fi_FI.json index f2ee2047ba7..3ec8cc30043 100644 --- a/lib/l10n/fi_FI.json +++ b/lib/l10n/fi_FI.json @@ -4,6 +4,7 @@ "See %s" : "Katso %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Tämän voi yleensä korjata antamalla %shttp-palvelimelle kirjoitusoikeuden asetushakemistoon%s.", "Sample configuration detected" : "Esimerkkimääritykset havaittu", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "On havaittu, että esimerkkimäärityksen on kopioitu. Se voi rikkoa asennuksesi, eikä sitä tueta. Lue ohjeet ennen kuin muutat config.php tiedostoa.", "PHP %s or higher is required." : "PHP %s tai sitä uudempi vaaditaan.", "PHP with a version lower than %s is required." : "PHP versiota %s alempi tarvitaan.", "%sbit or higher PHP required." : "%s-bit tai korkeampi PHP vaaditaan.", @@ -13,6 +14,8 @@ "Library %s with a version higher than %s is required - available version %s." : "Kirjasto %s versiota %s tai uudempi vaaditaan - käytettävissä oleva versio %s.", "Library %s with a version lower than %s is required - available version %s." : "Kirjasto %s versiota alempi %s tarvitaan - käytettävissä oleva versio %s.", "Following platforms are supported: %s" : "Seuraavat alustat ovat tuettuja: %s", + "Server version %s or higher is required." : "Palvelinversio %s tai sitä uudempi vaaditaan.", + "Server version %s or lower is required." : "Palvelinversio %s tai alhaisempi vaaditaan.", "Unknown filetype" : "Tuntematon tiedostotyyppi", "Invalid image" : "Virheellinen kuva", "today" : "tänään", @@ -29,6 +32,7 @@ "Empty filename is not allowed" : "Tiedostonimi ei voi olla tyhjä", "Dot files are not allowed" : "Pistetiedostot eivät ole sallittuja", "4-byte characters are not supported in file names" : "4 tavun merkit eivät ole tuettuja tiedostojen nimissä", + "File name is a reserved word" : "Tiedoston nimi on varattu sana", "File name contains at least one invalid character" : "Tiedoston nimi sisältää ainakin yhden virheellisen merkin", "File name is too long" : "Tiedoston nimi on liian pitkä", "App directory already exists" : "Sovelluskansio on jo olemassa", @@ -43,6 +47,8 @@ "App cannot be installed because appinfo file cannot be read." : "Sovellusta ei voi asentaa, koska appinfo-tiedostoa ei voi lukea.", "Signature could not get checked. Please contact the app developer and check your admin screen." : "Allekirjoituksen tarkistaminen ei onnistunut. Ota yhteys sovelluskehittäjään ja tarkista ylläpitonäkymä.", "App can't be installed because of not allowed code in the App" : "Sovellusta ei voi asentaa, koska sovellus sisältää kiellettyä koodia", + "App can't be installed because it is not compatible with this version of the server" : "Sovelluksen asennus ei onnistu, koska se ei ole yhteensopiva tämän palvelinversion kanssa.", + "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Sovelluksen asennus ei onnistu, koska se sisältää <shipped>true</shipped> tunnisteen, jota ei sallita sovelluksille, joita ei toimiteta Nextcloudin mukana.", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Sovelluksen asennus ei onnistu, koska sen info.xml:ssä ilmoitettu versio ei ole sama kuin sovelluskaupassa ilmoitettu versio", "APCu" : "APCu", "Redis" : "Redis", @@ -52,6 +58,7 @@ "Logging" : "Loki", "Additional settings" : "Lisäasetukset", "Tips & tricks" : "Vinkkejä", + "%s enter the database username and name." : "%s anna tietokannan käyttäjätunnus ja nimi.", "%s enter the database username." : "%s anna tietokannan käyttäjätunnus.", "%s enter the database name." : "%s anna tietokannan nimi.", "%s you may not use dots in the database name" : "%s et voi käyttää pisteitä tietokannan nimessä", @@ -59,6 +66,7 @@ "Oracle username and/or password not valid" : "Oraclen käyttäjätunnus ja/tai salasana on väärin", "DB Error: \"%s\"" : "Tietokantavirhe: \"%s\"", "Offending command was: \"%s\"" : "Loukkaava komento oli: \"%s\"", + "You need to enter either an existing account or the administrator." : "Sinun täytyy antaa joko olemassa oleva tili tai ylläpitäjä.", "Offending command was: \"%s\", name: %s, password: %s" : "Loukkaava komento oli: \"%s\", nimi: %s, salasana: %s", "PostgreSQL username and/or password not valid" : "PostgreSQL:n käyttäjätunnus ja/tai salasana on väärin", "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ei ole tuettu, joten %s ei toimi kunnolla tällä alustalla. Käytä omalla vastuulla!", @@ -67,8 +75,10 @@ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Poista open_basedir-asetus php.ini-tiedostosta tai vaihda 64-bittiseen PHP:hen.", "Set an admin username." : "Aseta ylläpitäjän käyttäjätunnus.", "Set an admin password." : "Aseta ylläpitäjän salasana.", + "Can't create or write into the data directory %s" : "Ei voi luoda tai kirjoittaa data -hakemistoon %s", "Invalid Federated Cloud ID" : "Virheellinen federoidun pilven tunniste", "%s shared »%s« with you" : "%s jakoi kohteen »%s« kanssasi", + "Sharing %s failed, because the backend does not allow shares from type %i" : "Kohteen %s jakaminen epäonnistui, koska tietovarasto ei salli %i tyyppisiä jakoja", "Sharing %s failed, because the file does not exist" : "Kohteen %s jakaminen epäonnistui, koska tiedostoa ei ole olemassa", "You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.", "Sharing %s failed, because you can not share with yourself" : "Kohteen %s jakaminen epäonnistui, koska et voi jakaa itsesi kanssa", diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index 48d1828ec28..6e9dd08a049 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -177,8 +177,8 @@ OC.L10N.register( "Storage connection error. %s" : "Erreur de connexion à l'espace stockage. %s", "Storage not available" : "Support de stockage non disponible", "Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s", - "ownCloud %s or higher is required." : "ownCloud %s ou supérieur est requis.", - "ownCloud %s or lower is required." : "ownCloud %sou inférieur est requis.", + "ownCloud %s or higher is required." : "Nextcloud %s ou supérieur est requis.", + "ownCloud %s or lower is required." : "Nextcloud %s ou inférieur est requis.", "App \"%s\" cannot be installed because it is not compatible with this version of Nextcloud." : "L'application \"%s\" ne peut être installée car elle n'est pas compatible avec cette version de Nextcloud.", "App can't be installed because it is not compatible with this version of Nextcloud" : "L'application ne peut être installée car elle n'est pas compatible avec cette version de Nextcloud", "App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" : "L'application ne peut être installée car la version dans info.xml/version n'est pas la même que la version signalée sur l'app store", diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index 03d57754fc9..430317014a6 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -175,8 +175,8 @@ "Storage connection error. %s" : "Erreur de connexion à l'espace stockage. %s", "Storage not available" : "Support de stockage non disponible", "Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s", - "ownCloud %s or higher is required." : "ownCloud %s ou supérieur est requis.", - "ownCloud %s or lower is required." : "ownCloud %sou inférieur est requis.", + "ownCloud %s or higher is required." : "Nextcloud %s ou supérieur est requis.", + "ownCloud %s or lower is required." : "Nextcloud %s ou inférieur est requis.", "App \"%s\" cannot be installed because it is not compatible with this version of Nextcloud." : "L'application \"%s\" ne peut être installée car elle n'est pas compatible avec cette version de Nextcloud.", "App can't be installed because it is not compatible with this version of Nextcloud" : "L'application ne peut être installée car elle n'est pas compatible avec cette version de Nextcloud", "App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" : "L'application ne peut être installée car la version dans info.xml/version n'est pas la même que la version signalée sur l'app store", diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 5fc200a1bce..21d5eaa9503 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -161,6 +161,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $this->getServer()->getRootFolder(); }); + $this->registerService('OCP\\Files\\Folder', function() { + return $this->getServer()->getUserFolder(); + }); + $this->registerService('OCP\\Http\\Client\\IClientService', function($c) { return $this->getServer()->getHTTPClientService(); }); diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php index 59678775d88..b3ecab731e1 100644 --- a/lib/private/Comments/Manager.php +++ b/lib/private/Comments/Manager.php @@ -26,6 +26,7 @@ namespace OC\Comments; use Doctrine\DBAL\Exception\DriverException; use OCP\Comments\CommentsEvent; use OCP\Comments\IComment; +use OCP\Comments\ICommentsEventHandler; use OCP\Comments\ICommentsManager; use OCP\Comments\NotFoundException; use OCP\DB\QueryBuilder\IQueryBuilder; @@ -33,7 +34,6 @@ use OCP\IDBConnection; use OCP\IConfig; use OCP\ILogger; use OCP\IUser; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Manager implements ICommentsManager { @@ -46,30 +46,30 @@ class Manager implements ICommentsManager { /** @var IConfig */ protected $config; - /** @var EventDispatcherInterface */ - protected $dispatcher; - /** @var IComment[] */ protected $commentsCache = []; + /** @var \Closure[] */ + protected $eventHandlerClosures = []; + + /** @var ICommentsEventHandler[] */ + protected $eventHandlers = []; + /** * Manager constructor. * * @param IDBConnection $dbConn * @param ILogger $logger * @param IConfig $config - * @param EventDispatcherInterface $dispatcher */ public function __construct( IDBConnection $dbConn, ILogger $logger, - IConfig $config, - EventDispatcherInterface $dispatcher + IConfig $config ) { $this->dbConn = $dbConn; $this->logger = $logger; $this->config = $config; - $this->dispatcher = $dispatcher; } /** @@ -455,10 +455,7 @@ class Manager implements ICommentsManager { } if ($affectedRows > 0 && $comment instanceof IComment) { - $this->dispatcher->dispatch(CommentsEvent::EVENT_DELETE, new CommentsEvent( - CommentsEvent::EVENT_DELETE, - $comment - )); + $this->sendEvent(CommentsEvent::EVENT_DELETE, $comment); } return ($affectedRows > 0); @@ -525,13 +522,9 @@ class Manager implements ICommentsManager { if ($affectedRows > 0) { $comment->setId(strval($qb->getLastInsertId())); + $this->sendEvent(CommentsEvent::EVENT_ADD, $comment); } - $this->dispatcher->dispatch(CommentsEvent::EVENT_ADD, new CommentsEvent( - CommentsEvent::EVENT_ADD, - $comment - )); - return $affectedRows > 0; } @@ -543,6 +536,12 @@ class Manager implements ICommentsManager { * @throws NotFoundException */ protected function update(IComment $comment) { + // for properly working preUpdate Events we need the old comments as is + // in the DB and overcome caching. Also avoid that outdated information stays. + $this->uncache($comment->getId()); + $this->sendEvent(CommentsEvent::EVENT_PRE_UPDATE, $this->get($comment->getId())); + $this->uncache($comment->getId()); + $qb = $this->dbConn->getQueryBuilder(); $affectedRows = $qb ->update('comments') @@ -565,10 +564,7 @@ class Manager implements ICommentsManager { throw new NotFoundException('Comment to update does ceased to exist'); } - $this->dispatcher->dispatch(CommentsEvent::EVENT_UPDATE, new CommentsEvent( - CommentsEvent::EVENT_UPDATE, - $comment - )); + $this->sendEvent(CommentsEvent::EVENT_UPDATE, $comment); return $affectedRows > 0; } @@ -751,4 +747,51 @@ class Manager implements ICommentsManager { } return ($affectedRows > 0); } + + /** + * registers an Entity to the manager, so event notifications can be send + * to consumers of the comments infrastructure + * + * @param \Closure $closure + */ + public function registerEventHandler(\Closure $closure) { + $this->eventHandlerClosures[] = $closure; + $this->eventHandlers = []; + } + + /** + * returns valid, registered entities + * + * @return \OCP\Comments\ICommentsEventHandler[] + */ + private function getEventHandlers() { + if(!empty($this->eventHandlers)) { + return $this->eventHandlers; + } + + $this->eventHandlers = []; + foreach ($this->eventHandlerClosures as $name => $closure) { + $entity = $closure(); + if (!($entity instanceof ICommentsEventHandler)) { + throw new \InvalidArgumentException('The given entity does not implement the ICommentsEntity interface'); + } + $this->eventHandlers[$name] = $entity; + } + + return $this->eventHandlers; + } + + /** + * sends notifications to the registered entities + * + * @param $eventType + * @param IComment $comment + */ + private function sendEvent($eventType, IComment $comment) { + $entities = $this->getEventHandlers(); + $event = new CommentsEvent($eventType, $comment); + foreach ($entities as $entity) { + $entity->handle($event); + } + } } diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php index 74812b3ed8c..c4132a34431 100644 --- a/lib/private/Files/Config/CachedMountInfo.php +++ b/lib/private/Files/Config/CachedMountInfo.php @@ -54,6 +54,11 @@ class CachedMountInfo implements ICachedMountInfo { protected $mountId; /** + * @var string + */ + protected $rootInternalPath; + + /** * CachedMountInfo constructor. * * @param IUser $user @@ -61,13 +66,15 @@ class CachedMountInfo implements ICachedMountInfo { * @param int $rootId * @param string $mountPoint * @param int|null $mountId + * @param string $rootInternalPath */ - public function __construct(IUser $user, $storageId, $rootId, $mountPoint, $mountId = null) { + public function __construct(IUser $user, $storageId, $rootId, $mountPoint, $mountId = null, $rootInternalPath = '') { $this->user = $user; $this->storageId = $storageId; $this->rootId = $rootId; $this->mountPoint = $mountPoint; $this->mountId = $mountId; + $this->rootInternalPath = $rootInternalPath; } /** @@ -122,4 +129,13 @@ class CachedMountInfo implements ICachedMountInfo { public function getMountId() { return $this->mountId; } + + /** + * Get the internal path (within the storage) of the root of the mount + * + * @return string + */ + public function getRootInternalPath() { + return $this->rootInternalPath; + } } diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php index 4df813d57d0..40d463c5103 100644 --- a/lib/private/Files/Config/LazyStorageMountInfo.php +++ b/lib/private/Files/Config/LazyStorageMountInfo.php @@ -76,4 +76,13 @@ class LazyStorageMountInfo extends CachedMountInfo { public function getMountId() { return $this->mount->getMountId(); } + + /** + * Get the internal path (within the storage) of the root of the mount + * + * @return string + */ + public function getRootInternalPath() { + return $this->mount->getInternalPath($this->mount->getMountPoint()); + } } diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index bd8343fa440..e9e142d0d4b 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -31,6 +31,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\Config\ICachedMountInfo; use OCP\Files\Config\IUserMountCache; use OCP\Files\Mount\IMountPoint; +use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\ICache; use OCP\IDBConnection; @@ -187,7 +188,7 @@ class UserMountCache implements IUserMountCache { private function dbRowToMountInfo(array $row) { $user = $this->userManager->get($row['user_id']); - return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point'], $row['mount_id']); + return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point'], $row['mount_id'], isset($row['path'])? $row['path']:''); } /** @@ -197,8 +198,9 @@ class UserMountCache implements IUserMountCache { public function getMountsForUser(IUser $user) { if (!isset($this->mountsForUsers[$user->getUID()])) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id') - ->from('mounts') + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') + ->from('mounts', 'm') + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) ->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($user->getUID()))); $rows = $query->execute()->fetchAll(); @@ -214,8 +216,9 @@ class UserMountCache implements IUserMountCache { */ public function getMountsForStorageId($numericStorageId) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id') - ->from('mounts') + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') + ->from('mounts', 'm') + ->innerJoin('m', 'filecache', 'f' , $builder->expr()->eq('m.root_id', 'f.fileid')) ->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, IQueryBuilder::PARAM_INT))); $rows = $query->execute()->fetchAll(); @@ -229,8 +232,9 @@ class UserMountCache implements IUserMountCache { */ public function getMountsForRootId($rootFileId) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id') - ->from('mounts') + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') + ->from('mounts', 'm') + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) ->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, IQueryBuilder::PARAM_INT))); $rows = $query->execute()->fetchAll(); @@ -246,7 +250,7 @@ class UserMountCache implements IUserMountCache { private function getCacheInfoFromFileId($fileId) { if (!isset($this->cacheInfoCache[$fileId])) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage', 'path') + $query = $builder->select('storage', 'path', 'mimetype') ->from('filecache') ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))); @@ -254,7 +258,8 @@ class UserMountCache implements IUserMountCache { if (is_array($row)) { $this->cacheInfoCache[$fileId] = [ (int)$row['storage'], - $row['path'] + $row['path'], + (int)$row['mimetype'] ]; } else { throw new NotFoundException('File with id "' . $fileId . '" not found'); @@ -281,15 +286,10 @@ class UserMountCache implements IUserMountCache { if ($fileId === $mount->getRootId()) { return true; } - try { - list(, $internalMountPath) = $this->getCacheInfoFromFileId($mount->getRootId()); - } catch (NotFoundException $e) { - return false; - } + $internalMountPath = $mount->getRootInternalPath(); return $internalMountPath === '' || substr($internalPath, 0, strlen($internalMountPath) + 1) === $internalMountPath . '/'; }); - } /** diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index d835fea7f4c..113bb5a85c6 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -225,7 +225,7 @@ class Filesystem { * @param int $priority */ public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) { - if (self::$logWarningWhenAddingStorageWrapper) { + if (self::$logWarningWhenAddingStorageWrapper && $wrapperName !== 'readonly') { \OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [ 'wrapper' => $wrapperName, 'app' => 'filesystem', diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php index e67e4817e2a..353b89068cb 100644 --- a/lib/private/Files/Node/Folder.php +++ b/lib/private/Files/Node/Folder.php @@ -28,6 +28,7 @@ namespace OC\Files\Node; use OC\DB\QueryBuilder\Literal; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\Files\Config\ICachedMountInfo; use OCP\Files\FileInfo; use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; @@ -83,7 +84,7 @@ class Folder extends Node implements \OCP\Files\Folder { public function getDirectoryListing() { $folderContent = $this->view->getDirectoryContent($this->path); - return array_map(function(FileInfo $info) { + return array_map(function (FileInfo $info) { if ($info->getMimetype() === 'httpd/unix-directory') { return new Folder($this->root, $this->view, $info->getPath(), $info); } else { @@ -253,7 +254,7 @@ class Folder extends Node implements \OCP\Files\Folder { } } - return array_map(function(FileInfo $file) { + return array_map(function (FileInfo $file) { return $this->createNode($file->getPath(), $file); }, $files); } @@ -263,29 +264,48 @@ class Folder extends Node implements \OCP\Files\Folder { * @return \OC\Files\Node\Node[] */ public function getById($id) { + $mountCache = $this->root->getUserMountCache(); + $mountsContainingFile = $mountCache->getMountsForFileId((int)$id); $mounts = $this->root->getMountsIn($this->path); $mounts[] = $this->root->getMount($this->path); - // reverse the array so we start with the storage this view is in - // which is the most likely to contain the file we're looking for - $mounts = array_reverse($mounts); + /** @var IMountPoint[] $folderMounts */ + $folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) { + return $mountPoint->getMountPoint(); + }, $mounts), $mounts); + + /** @var ICachedMountInfo[] $mountsContainingFile */ + $mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) { + return isset($folderMounts[$cachedMountInfo->getMountPoint()]); + })); - $nodes = array(); - foreach ($mounts as $mount) { - /** - * @var \OC\Files\Mount\MountPoint $mount - */ - if ($mount->getStorage()) { - $cache = $mount->getStorage()->getCache(); - $internalPath = $cache->getPathById($id); - if (is_string($internalPath)) { - $fullPath = $mount->getMountPoint() . $internalPath; - if (!is_null($path = $this->getRelativePath($fullPath))) { - $nodes[] = $this->get($path); - } - } - } + if (count($mountsContainingFile) === 0) { + return []; } - return $nodes; + + // we only need to get the cache info once, since all mounts we found point to the same storage + + $mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()]; + $cacheEntry = $mount->getStorage()->getCache()->get((int)$id); + if (!$cacheEntry) { + return []; + } + // cache jails will hide the "true" internal path + $internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/'); + + $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) { + $mount = $folderMounts[$cachedMountInfo->getMountPoint()]; + $pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath())); + $pathRelativeToMount = ltrim($pathRelativeToMount, '/'); + $absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount; + return $this->root->createNode($absolutePath, new \OC\Files\FileInfo( + $absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount, + \OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount)) + )); + }, $mountsContainingFile); + + return array_filter($nodes, function (Node $node) { + return $this->getRelativePath($node->getPath()); + }); } public function getFreeSpace() { diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index 007847fb513..0cda2c8b822 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -31,6 +31,7 @@ namespace OC\Files\Node; use OC\Cache\CappedMemoryCache; use OC\Files\Mount\Manager; use OC\Files\Mount\MountPoint; +use OCP\Files\Config\IUserMountCache; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OC\Hooks\PublicEmitter; @@ -75,16 +76,23 @@ class Root extends Folder implements IRootFolder { private $userFolderCache; /** + * @var IUserMountCache + */ + private $userMountCache; + + /** * @param \OC\Files\Mount\Manager $manager * @param \OC\Files\View $view * @param \OC\User\User|null $user + * @param IUserMountCache $userMountCache */ - public function __construct($manager, $view, $user) { + public function __construct($manager, $view, $user, IUserMountCache $userMountCache) { parent::__construct($this, $view, ''); $this->mountManager = $manager; $this->user = $user; $this->emitter = new PublicEmitter(); $this->userFolderCache = new CappedMemoryCache(); + $this->userMountCache = $userMountCache; } /** @@ -361,4 +369,8 @@ class Root extends Folder implements IRootFolder { public function clearCache() { $this->userFolderCache = new CappedMemoryCache(); } + + public function getUserMountCache() { + return $this->userMountCache; + } } diff --git a/lib/private/Server.php b/lib/private/Server.php index b49e94b554e..291714b23d1 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -175,10 +175,10 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('SystemTagObjectMapper', function (Server $c) { return $c->query('SystemTagManagerFactory')->getObjectMapper(); }); - $this->registerService('RootFolder', function () { + $this->registerService('RootFolder', function (Server $c) { $manager = \OC\Files\Filesystem::getMountManager(null); $view = new View(); - $root = new Root($manager, $view, null); + $root = new Root($manager, $view, null, $c->getUserMountCache()); $connector = new HookConnector($root, $view); $connector->viewToNode(); return $root; diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index b4fe69a83e2..22cf5a3f65a 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -614,8 +614,11 @@ class Manager implements IManager { throw new \Exception($error); } + $oldShare = $share; $provider = $this->factory->getProviderForType($share->getShareType()); $share = $provider->create($share); + //reuse the node we already have + $share->setNode($oldShare->getNode()); // Post share hook $postHookData = [ diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php index c565809c078..e3e8482f4e1 100644 --- a/lib/private/Share20/Share.php +++ b/lib/private/Share20/Share.php @@ -160,7 +160,7 @@ class Share implements \OCP\Share\IShare { $nodes = $userFolder->getById($this->fileId); if (empty($nodes)) { - throw new NotFoundException(); + throw new NotFoundException('Node for share not found, fileid: ' . $this->fileId); } $this->node = $nodes[0]; diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index dec959820f8..4b56609ccfc 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -597,7 +597,6 @@ class Session implements IUserSession, Emitter { } $dbToken->setLastCheck($now); - $this->tokenProvider->updateToken($dbToken); return true; } @@ -608,7 +607,6 @@ class Session implements IUserSession, Emitter { return false; } $dbToken->setLastCheck($now); - $this->tokenProvider->updateToken($dbToken); return true; } diff --git a/lib/public/Comments/CommentsEvent.php b/lib/public/Comments/CommentsEvent.php index a0bff349fb4..0d8a783c107 100644 --- a/lib/public/Comments/CommentsEvent.php +++ b/lib/public/Comments/CommentsEvent.php @@ -32,9 +32,10 @@ use Symfony\Component\EventDispatcher\Event; */ class CommentsEvent extends Event { - const EVENT_ADD = 'OCP\Comments\ICommentsManager::addComment'; - const EVENT_UPDATE = 'OCP\Comments\ICommentsManager::updateComment'; - const EVENT_DELETE = 'OCP\Comments\ICommentsManager::deleteComment'; + const EVENT_ADD = 'OCP\Comments\ICommentsManager::addComment'; + const EVENT_PRE_UPDATE = 'OCP\Comments\ICommentsManager::preUpdateComment'; + const EVENT_UPDATE = 'OCP\Comments\ICommentsManager::updateComment'; + const EVENT_DELETE = 'OCP\Comments\ICommentsManager::deleteComment'; /** @var string */ protected $event; diff --git a/lib/public/Comments/ICommentsEventHandler.php b/lib/public/Comments/ICommentsEventHandler.php new file mode 100644 index 00000000000..33524199012 --- /dev/null +++ b/lib/public/Comments/ICommentsEventHandler.php @@ -0,0 +1,39 @@ +<?php +/** + * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Comments; + +/** + * Interface ICommentsEventHandler + * + * @package OCP\Comments + * @since 9.2.0 + */ +interface ICommentsEventHandler { + + /** + * @param CommentsEvent $event + * @since 9.2.0 + */ + public function handle(CommentsEvent $event); +} diff --git a/lib/public/Comments/ICommentsManager.php b/lib/public/Comments/ICommentsManager.php index f2edaaa5eaf..98169fb335f 100644 --- a/lib/public/Comments/ICommentsManager.php +++ b/lib/public/Comments/ICommentsManager.php @@ -237,4 +237,13 @@ interface ICommentsManager { */ public function deleteReadMarksOnObject($objectType, $objectId); + /** + * registers an Entity to the manager, so event notifications can be send + * to consumers of the comments infrastructure + * + * @param \Closure $closure + * @since 9.2.0 + */ + public function registerEventHandler(\Closure $closure); + } diff --git a/lib/public/Files/Config/ICachedMountInfo.php b/lib/public/Files/Config/ICachedMountInfo.php index 2986f1d98c5..f5c5bb87ead 100644 --- a/lib/public/Files/Config/ICachedMountInfo.php +++ b/lib/public/Files/Config/ICachedMountInfo.php @@ -68,4 +68,12 @@ interface ICachedMountInfo { * @since 9.1.0 */ public function getMountId(); + + /** + * Get the internal path (within the storage) of the root of the mount + * + * @return string + * @since 9.2.0 + */ + public function getRootInternalPath(); } |