Skip to content

adjust to enhanced WorkflowEngine in Nc 18 #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion appinfo/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,3 @@
*/

$app = new \OCA\WorkflowScript\AppInfo\Application();
$app->registerHooksAndListeners();
4 changes: 0 additions & 4 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,4 @@
<dependencies>
<nextcloud min-version="18" max-version="18" />
</dependencies>
<settings>
<admin>OCA\WorkflowScript\Settings\Admin</admin>
<admin-section>OCA\WorkflowScript\Settings\Section</admin-section>
</settings>
</info>
121 changes: 50 additions & 71 deletions js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,79 +19,58 @@
*/

(function() {
OCA.WorkflowScript = OCA.WorkflowScript || {};

/**
* @class OCA.WorkflowScript.Operation
*/
OCA.WorkflowScript.Operation =
OCA.WorkflowEngine.Operation.extend({
defaults: {
'class': 'OCA\\WorkflowScript\\Operation',
'name': '',
'checks': [],
'operation': ''
var Component = {
name: 'WorkflowScript',
render: function (createElement) {
var self = this
return createElement('div', {
style: {
width: '100%'
},
}, [
createElement('input', {
attrs: {
type: 'text'
},
domProps: {
value: self.value,
required: 'true'
},
style: {
width: '100%'
},
on: {
input: function (event) {
self.$emit('input', event.target.value)
}
}
}),
createElement('a', {
attrs: {
href: self.link
},
style: {
color: 'var(--color-text-maxcontrast)'
}
}, self.description)
])
},
props: {
value: ''
},
data: function () {
return {
description: t('workflow_script', 'Available placeholder variables are listed in the documentation') + '↗',
link: 'https://github.com/nextcloud/workflow_script#placeholders'
}
});

/**
* @class OCA.WorkflowScript.OperationsCollection
*
* collection for all configured operations
*/
OCA.WorkflowScript.OperationsCollection =
OCA.WorkflowEngine.OperationsCollection.extend({
model: OCA.WorkflowScript.Operation
});

/**
* @class OCA.WorkflowScript.OperationView
*
* this creates the view for a single operation
*/
OCA.WorkflowScript.OperationView =
OCA.WorkflowEngine.OperationView.extend({
model: OCA.WorkflowScript.Operation,
render: function() {
var $el = OCA.WorkflowEngine.OperationView.prototype.render.apply(this);
$el.find('input.operation-operation')
.css('width', '400px')
.attr("placeholder", t('workflow_script', 'command to execute'))
}
});
}
};

/**
* @class OCA.WorkflowScript.OperationsView
*
* this creates the view for configured operations
*/
OCA.WorkflowScript.OperationsView =
OCA.WorkflowEngine.OperationsView.extend({
initialize: function() {
OCA.WorkflowEngine.OperationsView.prototype.initialize.apply(this, [
'OCA\\WorkflowScript\\Operation'
]);
},
renderOperation: function(operation) {
var subView = new OCA.WorkflowScript.OperationView({
model: operation
});
OCA.WorkflowEngine.registerOperator({
id: 'OCA\\WorkflowScript\\Operation',
operation: '',
options: Component
});

OCA.WorkflowEngine.OperationsView.prototype.renderOperation.apply(this, [
subView
]);
}
});
})();


$(document).ready(function() {
OC.SystemTags.collection.fetch({
success: function() {
new OCA.WorkflowScript.OperationsView({
el: '#workflow_script .rules',
collection: new OCA.WorkflowScript.OperationsCollection()
});
}
});
});
50 changes: 7 additions & 43 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@
namespace OCA\WorkflowScript\AppInfo;

use OCA\WorkflowScript\Operation;
use OCP\AppFramework\QueryException;
use OCP\Files\Folder;
use OCP\Files\Node;
use OCP\ILogger;
use OCP\WorkflowEngine\IManager;
use Symfony\Component\EventDispatcher\GenericEvent;

class Application extends \OCP\AppFramework\App {

Expand All @@ -36,45 +34,11 @@ class Application extends \OCP\AppFramework\App {
*/
public function __construct() {
parent::__construct('workflow_script');
}

protected function handleEvent(Node $node, string $eventName, array $extra = []) {
// '', admin, 'files', 'path/to/file.txt'
list(,, $folder,) = explode('/', $node->getPath(), 4);
if($folder !== 'files' || $node instanceof Folder) {
return;
}

try {
$operation = $this->getContainer()->query(Operation::class);
/** @var Operation $operation */
$operation->considerScript($node, $eventName, $extra);
} catch (QueryException $e) {
$logger = $this->getContainer()->getServer()->getLogger();
$logger->logException($e, ['app' => 'workflow_script', 'level' => ILogger::ERROR]);
}
}

public function onCreate(Node $node) {
$this->handleEvent($node, 'create');
}

public function onUpdate(Node $node) {
$this->handleEvent($node, 'update');
}

public function onRename(Node $oldNode, Node $node) {
$this->handleEvent($node, 'rename', ['oldFilePath' => $oldNode->getPath()]);
}

/**
* Register the app to several events
*/
public function registerHooksAndListeners() {
$root = $this->getContainer()->getServer()->getRootFolder();
$root->listen('\OC\Files', 'postCreate', [$this, 'onCreate']);
$root->listen('\OC\Files', 'postWrite', [$this, 'onUpdate']);
$root->listen('\OC\Files', 'postRename', [$this, 'onRename']);
\OC::$server->getEventDispatcher()->addListener(IManager::EVENT_NAME_REG_OPERATION, function (GenericEvent $event) {
$operation = \OC::$server->query(Operation::class);
$event->getSubject()->registerOperation($operation);
\OC_Util::addScript('workflow_script', 'admin');
});
}

}
105 changes: 77 additions & 28 deletions lib/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,26 @@

namespace OCA\WorkflowScript;

use OC\Files\Node\File;
use OC\Files\Node\Folder;
use OC\Files\View;
use OCA\WorkflowEngine\Entity\File;
use OCA\WorkflowScript\BackgroundJobs\Launcher;
use OCP\BackgroundJob\IJobList;
use OCP\EventDispatcher\Event;
use OCP\Files\Folder;
use OCP\Files\InvalidPathException;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IL10N;
use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\MapperEvent;
use OCP\WorkflowEngine\IManager;
use OCP\WorkflowEngine\IOperation;
use OCP\WorkflowEngine\IRuleMatcher;
use OCP\WorkflowEngine\ISpecificOperation;
use Symfony\Component\EventDispatcher\GenericEvent;

class Operation implements IOperation {
class Operation implements ISpecificOperation {

/** @var IManager */
private $workflowEngineManager;
Expand All @@ -59,22 +63,6 @@ public function __construct(IManager $workflowEngineManager, IJobList $jobList,
$this->rootFolder = $rootFolder;
}

public function considerScript(Node $node, string $event, array $extra = []) {
try {
$this->workflowEngineManager->setFileInfo($node->getStorage(), $node->getInternalPath());
$matches = $this->workflowEngineManager->getMatchingOperations(Operation::class, false);
foreach ($matches as $match) {
$command = $this->buildCommand($match['operation'], $node, $event, $extra);
$args = ['command' => $command];
if (strpos($command, '%f')) {
$args['path'] = $node->getPath();
}
$this->jobList->add(Launcher::class, $args);
}
} catch (NotFoundException $e) {
}
}

protected function buildCommand(string $template, Node $node, string $event, array $extra = []) {
$command = $template;

Expand All @@ -89,13 +77,13 @@ protected function buildCommand(string $template, Node $node, string $event, arr

if (false && strpos($command, '%f')) {
try {
$view = new \OC\Files\View($node->getParent()->getPath());
if($node instanceof \OCP\Files\Folder) {
$view = new View($node->getParent()->getPath());
if ($node instanceof Folder) {
$fullPath = $view->getLocalFolder($node->getPath());
} else {
$fullPath = $view->getLocalFile($node->getPath());
}
if($fullPath === null) {
if ($fullPath === null) {
throw new \InvalidArgumentException();
}
//$fullPath = $node->getParent()->getFullPath($node->getPath());
Expand Down Expand Up @@ -144,13 +132,10 @@ protected function buildCommand(string $template, Node $node, string $event, arr
}

/**
* @param string $name
* @param array[] $checks
* @param string $operation
* @throws \UnexpectedValueException
* @since 9.1
*/
public function validateOperation($name, array $checks, $operation) {
public function validateOperation(string $name, array $checks, string $operation): void {
if (empty($operation)) {
throw new \UnexpectedValueException($this->l->t('Please provide a script name'));
}
Expand All @@ -169,4 +154,68 @@ protected function isScriptValid(string $scriptName) {

return is_executable($scriptName);
}

public function getDisplayName(): string {
return $this->l->t('External scripts');
}

public function getDescription(): string {
return $this->l->t('Pass files to external scripts for processing outside of Nextcloud');
}

public function getIcon(): string {
return \OC::$server->getURLGenerator()->imagePath('workflow_script', 'app.svg');
}

public function isAvailableForScope(int $scope): bool {
return $scope === IManager::SCOPE_ADMIN;
}

public function onEvent(string $eventName, Event $event, IRuleMatcher $ruleMatcher): void {
if (!$event instanceof GenericEvent && !$event instanceof MapperEvent) {
return;
}
try {
$extra = [];
if ($eventName === '\OCP\Files::postRename') {
/** @var Node $oldNode */
list($oldNode,) = $event->getSubject();
$extra = ['oldFilePath' => $oldNode->getPath()];
} else if ($event instanceof MapperEvent) {
if ($event->getObjectType() !== 'files') {
return;
}
$nodes = $this->rootFolder->getById($event->getObjectId());
if (!isset($nodes[0])) {
return;
}
$node = $nodes[0];
unset($nodes);
} else {
$node = $event->getSubject();
}
/** @var Node $node */

// '', admin, 'files', 'path/to/file.txt'
list(, , $folder,) = explode('/', $node->getPath(), 4);
if ($folder !== 'files' || $node instanceof Folder) {
return;
}

$matches = $ruleMatcher->getMatchingOperations(Operation::class, false);
foreach ($matches as $match) {
$command = $this->buildCommand($match['operation'], $node, $eventName, $extra);
$args = ['command' => $command];
if (strpos($command, '%f')) {
$args['path'] = $node->getPath();
}
$this->jobList->add(Launcher::class, $args);
}
} catch (NotFoundException $e) {
}
}

public function getEntityId(): string {
return File::class;
}
}
Loading