mirror of https://github.com/nextcloud/server
feat(files): copy live photos
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
This commit is contained in:
parent
9522ef8497
commit
467c84ec53
|
@ -61,8 +61,10 @@ use OCP\Collaboration\Reference\RenderReferenceEvent;
|
|||
use OCP\Collaboration\Resources\IProviderManager;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\Cache\CacheEntryRemovedEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeCopiedEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
|
||||
use OCP\Files\Events\Node\NodeCopiedEvent;
|
||||
use OCP\IConfig;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
|
@ -132,6 +134,8 @@ class Application extends App implements IBootstrap {
|
|||
$context->registerEventListener(BeforeNodeRestoredEvent::class, SyncLivePhotosListener::class);
|
||||
$context->registerEventListener(CacheEntryRemovedEvent::class, SyncLivePhotosListener::class);
|
||||
$context->registerEventListener(LoadSearchPlugins::class, LoadSearchPluginsListener::class);
|
||||
$context->registerEventListener(BeforeNodeCopiedEvent::class, SyncLivePhotosListener::class);
|
||||
$context->registerEventListener(NodeCopiedEvent::class, SyncLivePhotosListener::class);
|
||||
|
||||
$context->registerSearchProvider(FilesSearchProvider::class);
|
||||
|
||||
|
|
|
@ -29,9 +29,13 @@ use OCA\Files_Trashbin\Trash\ITrashItem;
|
|||
use OCA\Files_Trashbin\Trash\ITrashManager;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Exceptions\AbortedEventException;
|
||||
use OCP\Files\Cache\CacheEntryRemovedEvent;
|
||||
use OCP\Files\Events\Node\AbstractNodesEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeCopiedEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
|
||||
use OCP\Files\Events\Node\NodeCopiedEvent;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\Node;
|
||||
use OCP\Files\NotFoundException;
|
||||
|
@ -44,7 +48,7 @@ use OCP\IUserSession;
|
|||
* @template-implements IEventListener<Event>
|
||||
*/
|
||||
class SyncLivePhotosListener implements IEventListener {
|
||||
/** @var Array<int, string> */
|
||||
/** @var Array<int> */
|
||||
private array $pendingRenames = [];
|
||||
/** @var Array<int, bool> */
|
||||
private array $pendingDeletion = [];
|
||||
|
@ -65,7 +69,6 @@ class SyncLivePhotosListener implements IEventListener {
|
|||
}
|
||||
|
||||
$peerFile = null;
|
||||
|
||||
if ($event instanceof BeforeNodeRenamedEvent) {
|
||||
$peerFile = $this->getLivePhotoPeer($event->getSource()->getId());
|
||||
} elseif ($event instanceof BeforeNodeRestoredEvent) {
|
||||
|
@ -74,6 +77,8 @@ class SyncLivePhotosListener implements IEventListener {
|
|||
$peerFile = $this->getLivePhotoPeer($event->getNode()->getId());
|
||||
} elseif ($event instanceof CacheEntryRemovedEvent) {
|
||||
$peerFile = $this->getLivePhotoPeer($event->getFileId());
|
||||
} elseif ($event instanceof BeforeNodeCopiedEvent || $event instanceof NodeCopiedEvent) {
|
||||
$peerFile = $this->getLivePhotoPeer($event->getSource()->getId());
|
||||
}
|
||||
|
||||
if ($peerFile === null) {
|
||||
|
@ -81,13 +86,17 @@ class SyncLivePhotosListener implements IEventListener {
|
|||
}
|
||||
|
||||
if ($event instanceof BeforeNodeRenamedEvent) {
|
||||
$this->handleMove($event, $peerFile);
|
||||
$this->handleMove($event, $peerFile, false);
|
||||
} elseif ($event instanceof BeforeNodeDeletedEvent) {
|
||||
$this->handleDeletion($event, $peerFile);
|
||||
} elseif ($event instanceof CacheEntryRemovedEvent) {
|
||||
$peerFile->delete();
|
||||
} elseif ($event instanceof BeforeNodeRestoredEvent) {
|
||||
$this->handleRestore($event, $peerFile);
|
||||
} elseif ($event instanceof BeforeNodeCopiedEvent) {
|
||||
$this->handleMove($event, $peerFile, true);
|
||||
} elseif ($event instanceof NodeCopiedEvent) {
|
||||
$this->handleCopy($event, $peerFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,44 +107,79 @@ class SyncLivePhotosListener implements IEventListener {
|
|||
* of pending renames inside the 'pendingRenames' property,
|
||||
* to prevent infinite recursive.
|
||||
*/
|
||||
private function handleMove(BeforeNodeRenamedEvent $event, Node $peerFile): void {
|
||||
private function handleMove(AbstractNodesEvent $event, Node $peerFile, bool $prepForCopyOnly = false): void {
|
||||
if (!($event instanceof BeforeNodeCopiedEvent) &&
|
||||
!($event instanceof BeforeNodeRenamedEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sourceFile = $event->getSource();
|
||||
$targetFile = $event->getTarget();
|
||||
$targetParent = $targetFile->getParent();
|
||||
$sourceExtension = $sourceFile->getExtension();
|
||||
$peerFileExtension = $peerFile->getExtension();
|
||||
$targetName = $targetFile->getName();
|
||||
$targetPath = $targetFile->getPath();
|
||||
|
||||
if (!str_ends_with($targetName, ".".$sourceExtension)) {
|
||||
$event->abortOperation(new NotPermittedException("Cannot change the extension of a Live Photo"));
|
||||
if (!str_ends_with($targetName, "." . $sourceExtension)) {
|
||||
throw new AbortedEventException('Cannot change the extension of a Live Photo');
|
||||
}
|
||||
|
||||
try {
|
||||
$targetParent->get($targetName);
|
||||
$event->abortOperation(new NotPermittedException("A file already exist at destination path of the Live Photo"));
|
||||
} catch (NotFoundException $ex) {
|
||||
throw new AbortedEventException('A file already exist at destination path of the Live Photo');
|
||||
} catch (NotFoundException) {
|
||||
}
|
||||
|
||||
$peerTargetName = substr($targetName, 0, -strlen($sourceExtension)) . $peerFileExtension;
|
||||
try {
|
||||
$targetParent->get($peerTargetName);
|
||||
$event->abortOperation(new NotPermittedException("A file already exist at destination path of the Live Photo"));
|
||||
} catch (NotFoundException $ex) {
|
||||
throw new AbortedEventException('A file already exist at destination path of the Live Photo');
|
||||
} catch (NotFoundException) {
|
||||
}
|
||||
|
||||
// in case the rename was initiated from this listener, we stop right now
|
||||
if (array_key_exists($peerFile->getId(), $this->pendingRenames)) {
|
||||
if ($prepForCopyOnly || in_array($peerFile->getId(), $this->pendingRenames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->pendingRenames[$sourceFile->getId()] = $targetPath;
|
||||
$this->pendingRenames[] = $sourceFile->getId();
|
||||
try {
|
||||
$peerFile->move($targetParent->getPath() . '/' . $peerTargetName);
|
||||
} catch (\Throwable $ex) {
|
||||
$event->abortOperation($ex);
|
||||
throw new AbortedEventException($ex->getMessage());
|
||||
}
|
||||
unset($this->pendingRenames[$sourceFile->getId()]);
|
||||
|
||||
array_diff($this->pendingRenames, [$sourceFile->getId()]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* handle copy, we already know if it is doable from BeforeNodeCopiedEvent, so we just copy the linked file
|
||||
*
|
||||
* @param NodeCopiedEvent $event
|
||||
* @param Node $peerFile
|
||||
*/
|
||||
private function handleCopy(NodeCopiedEvent $event, Node $peerFile): void {
|
||||
$sourceFile = $event->getSource();
|
||||
$sourceExtension = $sourceFile->getExtension();
|
||||
$peerFileExtension = $peerFile->getExtension();
|
||||
$targetFile = $event->getTarget();
|
||||
$targetParent = $targetFile->getParent();
|
||||
$targetName = $targetFile->getName();
|
||||
$peerTargetName = substr($targetName, 0, -strlen($sourceExtension)) . $peerFileExtension;
|
||||
|
||||
/**
|
||||
* let's use freshly set variable.
|
||||
* we copy the file and get its id. We already have the id of the current copy
|
||||
* We have everything to update metadata and keep the link between the 2 copies.
|
||||
*/
|
||||
$newPeerFile = $peerFile->copy($targetParent->getPath() . '/' . $peerTargetName);
|
||||
$targetMetadata = $this->filesMetadataManager->getMetadata($targetFile->getId(), true);
|
||||
$targetMetadata->setString('files-live-photo', (string)$newPeerFile->getId());
|
||||
$this->filesMetadataManager->saveMetadata($targetMetadata);
|
||||
$peerMetadata = $this->filesMetadataManager->getMetadata($newPeerFile->getId(), true);
|
||||
$peerMetadata->setString('files-live-photo', (string)$targetFile->getId());
|
||||
$this->filesMetadataManager->saveMetadata($peerMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,14 +196,14 @@ class SyncLivePhotosListener implements IEventListener {
|
|||
unset($this->pendingDeletion[$peerFile->getId()]);
|
||||
return;
|
||||
} else {
|
||||
$event->abortOperation(new NotPermittedException("Cannot delete the video part of a live photo"));
|
||||
throw new AbortedEventException("Cannot delete the video part of a live photo");
|
||||
}
|
||||
} else {
|
||||
$this->pendingDeletion[$deletedFile->getId()] = true;
|
||||
try {
|
||||
$peerFile->delete();
|
||||
} catch (\Throwable $ex) {
|
||||
$event->abortOperation($ex);
|
||||
throw new AbortedEventException($ex->getMessage());
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -276,6 +276,7 @@ return array(
|
|||
'OCP\\EventDispatcher\\GenericEvent' => $baseDir . '/lib/public/EventDispatcher/GenericEvent.php',
|
||||
'OCP\\EventDispatcher\\IEventDispatcher' => $baseDir . '/lib/public/EventDispatcher/IEventDispatcher.php',
|
||||
'OCP\\EventDispatcher\\IEventListener' => $baseDir . '/lib/public/EventDispatcher/IEventListener.php',
|
||||
'OCP\\Exceptions\\AbortedEventException' => $baseDir . '/lib/public/Exceptions/AbortedEventException.php',
|
||||
'OCP\\Exceptions\\AppConfigException' => $baseDir . '/lib/public/Exceptions/AppConfigException.php',
|
||||
'OCP\\Exceptions\\AppConfigIncorrectTypeException' => $baseDir . '/lib/public/Exceptions/AppConfigIncorrectTypeException.php',
|
||||
'OCP\\Exceptions\\AppConfigTypeConflictException' => $baseDir . '/lib/public/Exceptions/AppConfigTypeConflictException.php',
|
||||
|
|
|
@ -309,6 +309,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\EventDispatcher\\GenericEvent' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/GenericEvent.php',
|
||||
'OCP\\EventDispatcher\\IEventDispatcher' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventDispatcher.php',
|
||||
'OCP\\EventDispatcher\\IEventListener' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventListener.php',
|
||||
'OCP\\Exceptions\\AbortedEventException' => __DIR__ . '/../../..' . '/lib/public/Exceptions/AbortedEventException.php',
|
||||
'OCP\\Exceptions\\AppConfigException' => __DIR__ . '/../../..' . '/lib/public/Exceptions/AppConfigException.php',
|
||||
'OCP\\Exceptions\\AppConfigIncorrectTypeException' => __DIR__ . '/../../..' . '/lib/public/Exceptions/AppConfigIncorrectTypeException.php',
|
||||
'OCP\\Exceptions\\AppConfigTypeConflictException' => __DIR__ . '/../../..' . '/lib/public/Exceptions/AppConfigTypeConflictException.php',
|
||||
|
|
|
@ -6,6 +6,7 @@ declare(strict_types=1);
|
|||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
|
@ -30,6 +31,7 @@ use OC\Files\Filesystem;
|
|||
use OC\Files\View;
|
||||
use OCP\EventDispatcher\GenericEvent;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Exceptions\AbortedEventException;
|
||||
use OCP\Files\Events\Node\BeforeNodeCopiedEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeCreatedEvent;
|
||||
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
|
||||
|
@ -46,27 +48,18 @@ use OCP\Files\Events\Node\NodeWrittenEvent;
|
|||
use OCP\Files\FileInfo;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Util;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class HookConnector {
|
||||
/** @var IRootFolder */
|
||||
private $root;
|
||||
|
||||
/** @var View */
|
||||
private $view;
|
||||
|
||||
/** @var FileInfo[] */
|
||||
private $deleteMetaCache = [];
|
||||
|
||||
/** @var IEventDispatcher */
|
||||
private $dispatcher;
|
||||
private array $deleteMetaCache = [];
|
||||
|
||||
public function __construct(
|
||||
IRootFolder $root,
|
||||
View $view,
|
||||
IEventDispatcher $dispatcher) {
|
||||
$this->root = $root;
|
||||
$this->view = $view;
|
||||
$this->dispatcher = $dispatcher;
|
||||
private IRootFolder $root,
|
||||
private View $view,
|
||||
private IEventDispatcher $dispatcher,
|
||||
private LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
public function viewToNode() {
|
||||
|
@ -133,8 +126,13 @@ class HookConnector {
|
|||
$this->root->emit('\OC\Files', 'preDelete', [$node]);
|
||||
$this->dispatcher->dispatch('\OCP\Files::preDelete', new GenericEvent($node));
|
||||
|
||||
$event = new BeforeNodeDeletedEvent($node, $arguments['run']);
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
$event = new BeforeNodeDeletedEvent($node);
|
||||
try {
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
} catch (AbortedEventException $e) {
|
||||
$arguments['run'] = false;
|
||||
$this->logger->warning('delete process aborted', ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
|
||||
public function postDelete($arguments) {
|
||||
|
@ -171,8 +169,13 @@ class HookConnector {
|
|||
$this->root->emit('\OC\Files', 'preRename', [$source, $target]);
|
||||
$this->dispatcher->dispatch('\OCP\Files::preRename', new GenericEvent([$source, $target]));
|
||||
|
||||
$event = new BeforeNodeRenamedEvent($source, $target, $arguments['run']);
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
$event = new BeforeNodeRenamedEvent($source, $target);
|
||||
try {
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
} catch (AbortedEventException $e) {
|
||||
$arguments['run'] = false;
|
||||
$this->logger->warning('rename process aborted', ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
|
||||
public function postRename($arguments) {
|
||||
|
@ -192,7 +195,12 @@ class HookConnector {
|
|||
$this->dispatcher->dispatch('\OCP\Files::preCopy', new GenericEvent([$source, $target]));
|
||||
|
||||
$event = new BeforeNodeCopiedEvent($source, $target);
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
try {
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
} catch (AbortedEventException $e) {
|
||||
$arguments['run'] = false;
|
||||
$this->logger->warning('copy process aborted', ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
|
||||
public function postCopy($arguments) {
|
||||
|
|
|
@ -475,7 +475,8 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
return new HookConnector(
|
||||
$c->get(IRootFolder::class),
|
||||
new View(),
|
||||
$c->get(IEventDispatcher::class)
|
||||
$c->get(IEventDispatcher::class),
|
||||
$c->get(LoggerInterface::class)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright 2023 Maxence Lange <maxence@artificial-owl.com>
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
*
|
||||
* @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\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @since 29.0.0
|
||||
*/
|
||||
class AbortedEventException extends Exception {
|
||||
}
|
|
@ -32,14 +32,12 @@ use OCP\Files\Node;
|
|||
* @since 20.0.0
|
||||
*/
|
||||
abstract class AbstractNodeEvent extends Event {
|
||||
/** @var Node */
|
||||
private $node;
|
||||
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
public function __construct(Node $node) {
|
||||
$this->node = $node;
|
||||
public function __construct(
|
||||
private Node $node
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,17 +32,13 @@ use OCP\Files\Node;
|
|||
* @since 20.0.0
|
||||
*/
|
||||
abstract class AbstractNodesEvent extends Event {
|
||||
/** @var Node */
|
||||
private $source;
|
||||
/** @var Node */
|
||||
private $target;
|
||||
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
public function __construct(Node $source, Node $target) {
|
||||
$this->source = $source;
|
||||
$this->target = $target;
|
||||
public function __construct(
|
||||
private Node $source,
|
||||
private Node $target
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,31 +25,17 @@ declare(strict_types=1);
|
|||
*/
|
||||
namespace OCP\Files\Events\Node;
|
||||
|
||||
use Exception;
|
||||
use OCP\Files\Node;
|
||||
use OCP\Exceptions\AbortedEventException;
|
||||
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
class BeforeNodeDeletedEvent extends AbstractNodeEvent {
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
public function __construct(Node $node, private bool &$run) {
|
||||
parent::__construct($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @return never
|
||||
* @deprecated 29.0.0 - use OCP\Exceptions\AbortedEventException instead
|
||||
*/
|
||||
public function abortOperation(\Throwable $ex = null) {
|
||||
$this->stopPropagation();
|
||||
$this->run = false;
|
||||
if ($ex !== null) {
|
||||
throw $ex;
|
||||
} else {
|
||||
throw new Exception('Operation aborted');
|
||||
}
|
||||
throw new AbortedEventException($ex?->getMessage() ?? 'Operation aborted');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,31 +25,17 @@ declare(strict_types=1);
|
|||
*/
|
||||
namespace OCP\Files\Events\Node;
|
||||
|
||||
use Exception;
|
||||
use OCP\Files\Node;
|
||||
use OCP\Exceptions\AbortedEventException;
|
||||
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
class BeforeNodeRenamedEvent extends AbstractNodesEvent {
|
||||
/**
|
||||
* @since 20.0.0
|
||||
*/
|
||||
public function __construct(Node $source, Node $target, private bool &$run) {
|
||||
parent::__construct($source, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @return never
|
||||
* @deprecated 29.0.0 - use OCP\Exceptions\AbortedEventException instead
|
||||
*/
|
||||
public function abortOperation(\Throwable $ex = null) {
|
||||
$this->stopPropagation();
|
||||
$this->run = false;
|
||||
if ($ex !== null) {
|
||||
throw $ex;
|
||||
} else {
|
||||
throw new Exception('Operation aborted');
|
||||
}
|
||||
throw new AbortedEventException($ex?->getMessage() ?? 'Operation aborted');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ class HookConnectorTest extends TestCase {
|
|||
/** @var IEventDispatcher */
|
||||
protected $eventDispatcher;
|
||||
|
||||
private LoggerInterface $logger;
|
||||
|
||||
/** @var View */
|
||||
private $view;
|
||||
|
||||
|
@ -86,6 +88,7 @@ class HookConnectorTest extends TestCase {
|
|||
$cacheFactory,
|
||||
);
|
||||
$this->eventDispatcher = \OC::$server->query(IEventDispatcher::class);
|
||||
$this->logger = \OC::$server->query(LoggerInterface::class);
|
||||
}
|
||||
|
||||
protected function tearDown(): void {
|
||||
|
@ -151,7 +154,7 @@ class HookConnectorTest extends TestCase {
|
|||
* @dataProvider viewToNodeProvider
|
||||
*/
|
||||
public function testViewToNode(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent) {
|
||||
$connector = new HookConnector($this->root, $this->view, $this->eventDispatcher);
|
||||
$connector = new HookConnector($this->root, $this->view, $this->eventDispatcher, $this->logger);
|
||||
$connector->viewToNode();
|
||||
$hookCalled = false;
|
||||
/** @var Node $hookNode */
|
||||
|
@ -220,7 +223,7 @@ class HookConnectorTest extends TestCase {
|
|||
* @dataProvider viewToNodeProviderCopyRename
|
||||
*/
|
||||
public function testViewToNodeCopyRename(callable $operation, $expectedHook, $expectedLegacyEvent, $expectedEvent) {
|
||||
$connector = new HookConnector($this->root, $this->view, $this->eventDispatcher);
|
||||
$connector = new HookConnector($this->root, $this->view, $this->eventDispatcher, $this->logger);
|
||||
$connector->viewToNode();
|
||||
$hookCalled = false;
|
||||
/** @var Node $hookSourceNode */
|
||||
|
@ -275,7 +278,7 @@ class HookConnectorTest extends TestCase {
|
|||
}
|
||||
|
||||
public function testPostDeleteMeta() {
|
||||
$connector = new HookConnector($this->root, $this->view, $this->eventDispatcher);
|
||||
$connector = new HookConnector($this->root, $this->view, $this->eventDispatcher, $this->logger);
|
||||
$connector->viewToNode();
|
||||
$hookCalled = false;
|
||||
/** @var Node $hookNode */
|
||||
|
|
Loading…
Reference in New Issue