From 412e4ed3f669b61f155b5ef1bc6d50168f5ea131 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 18 Dec 2015 11:43:39 +0100 Subject: [PATCH 1/4] Register app containers in the OC container --- .../dependencyinjection/dicontainer.php | 4 ++ lib/private/server.php | 2 +- lib/private/servercontainer.php | 65 +++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 lib/private/servercontainer.php diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php index ce6523cc8a..88ffc1c6f9 100644 --- a/lib/private/appframework/dependencyinjection/dicontainer.php +++ b/lib/private/appframework/dependencyinjection/dicontainer.php @@ -62,6 +62,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { $this['AppName'] = $appName; $this['urlParams'] = $urlParams; + /** @var \OC\ServerContainer $server */ + $server = $this->getServer(); + $server->registerAppContainer($appName, $this); + // aliases $this->registerAlias('appName', 'AppName'); $this->registerAlias('webRoot', 'WebRoot'); diff --git a/lib/private/server.php b/lib/private/server.php index 8439500706..5e29dbedc4 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -78,7 +78,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; * * TODO: hookup all manager classes */ -class Server extends SimpleContainer implements IServerContainer { +class Server extends ServerContainer implements IServerContainer { /** @var string */ private $webRoot; diff --git a/lib/private/servercontainer.php b/lib/private/servercontainer.php new file mode 100644 index 0000000000..469fd6475e --- /dev/null +++ b/lib/private/servercontainer.php @@ -0,0 +1,65 @@ + + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC; + + +use OC\AppFramework\DependencyInjection\DIContainer; +use OC\AppFramework\Utility\SimpleContainer; +use OCP\AppFramework\QueryException; + +/** + * Class ServerContainer + * + * @package OC + */ +class ServerContainer extends SimpleContainer { + /** @var DIContainer[] */ + protected $appContainers; + + /** + * ServerContainer constructor. + */ + public function __construct() { + parent::__construct(); + $this->appContainers = []; + } + + /** + * @param string $appName + * @param DIContainer $container + */ + public function registerAppContainer($appName, DIContainer $container) { + $this->appContainers[$appName] = $container; + } + + /** + * @param string $appName + * @return DIContainer + */ + public function getAppContainer($appName) { + if (isset($this->appContainers[$appName])) { + return $this->appContainers[$appName]; + } + + return new DIContainer($appName); + } +} From 1f197134c87836167142cc766bdaab572fb73b8d Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 18 Dec 2015 11:44:10 +0100 Subject: [PATCH 2/4] Look up services in the app container before trying the core container --- lib/private/servercontainer.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/private/servercontainer.php b/lib/private/servercontainer.php index 469fd6475e..856e3f9b49 100644 --- a/lib/private/servercontainer.php +++ b/lib/private/servercontainer.php @@ -62,4 +62,28 @@ class ServerContainer extends SimpleContainer { return new DIContainer($appName); } + + /** + * @param string $name name of the service to query for + * @return mixed registered service for the given $name + * @throws QueryException if the query could not be resolved + */ + public function query($name) { + $name = $this->sanitizeName($name); + + // In case the service starts with OCA\ we try to find the service in + // the apps container first. + if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) { + $segments = explode('\\', $name); + $appContainer = $this->getAppContainer(strtolower($segments[0])); + try { + return $appContainer->query($name); + } catch (QueryException $e) { + // Didn't find the service in the respective app container, + // ignore it and fall back to the core container. + } + } + + return parent::query($name); + } } From 0daed65e1466cc96584b5043795678ade0698fb0 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 18 Dec 2015 11:44:32 +0100 Subject: [PATCH 3/4] Allow dependency injection for background jobs --- lib/private/backgroundjob/joblist.php | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/private/backgroundjob/joblist.php b/lib/private/backgroundjob/joblist.php index 75c205833f..3618b0f9e5 100644 --- a/lib/private/backgroundjob/joblist.php +++ b/lib/private/backgroundjob/joblist.php @@ -24,6 +24,7 @@ namespace OC\BackgroundJob; +use OCP\AppFramework\QueryException; use OCP\BackgroundJob\IJob; use OCP\BackgroundJob\IJobList; use OCP\AutoloadNotAllowedException; @@ -232,24 +233,29 @@ class JobList implements IJobList { * @return IJob|null */ private function buildJob($row) { - $class = $row['class']; - /** - * @var Job $job - */ try { - if (!class_exists($class)) { - // job from disabled app or old version of an app, no need to do anything - return null; + try { + // Try to load the job as a service + /** @var Job $job */ + $job = \OC::$server->query($row['class']); + } catch (QueryException $e) { + if (class_exists($row['class'])) { + $class = $row['class']; + $job = new $class(); + } else { + // job from disabled app or old version of an app, no need to do anything + return null; + } } - $job = new $class(); + $job->setId($row['id']); $job->setLastRun($row['last_run']); $job->setArgument(json_decode($row['argument'], true)); return $job; } catch (AutoloadNotAllowedException $e) { // job is from a disabled app, ignore + return null; } - return null; } /** From a9935bd49042e3c4a35630a980bf7e1c6d56ff20 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 18 Dec 2015 14:16:32 +0100 Subject: [PATCH 4/4] Add methods to interface which have always been required --- lib/private/backgroundjob/joblist.php | 2 +- lib/public/backgroundjob/ijob.php | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/private/backgroundjob/joblist.php b/lib/private/backgroundjob/joblist.php index 3618b0f9e5..446de2fa1a 100644 --- a/lib/private/backgroundjob/joblist.php +++ b/lib/private/backgroundjob/joblist.php @@ -236,7 +236,7 @@ class JobList implements IJobList { try { try { // Try to load the job as a service - /** @var Job $job */ + /** @var IJob $job */ $job = \OC::$server->query($row['class']); } catch (QueryException $e) { if (class_exists($row['class'])) { diff --git a/lib/public/backgroundjob/ijob.php b/lib/public/backgroundjob/ijob.php index a24a543452..8d970dbe78 100644 --- a/lib/public/backgroundjob/ijob.php +++ b/lib/public/backgroundjob/ijob.php @@ -36,11 +36,28 @@ interface IJob { * * @param \OCP\BackgroundJob\IJobList $jobList The job list that manages the state of this job * @param ILogger $logger - * @return void * @since 7.0.0 */ public function execute($jobList, ILogger $logger = null); + /** + * @param int $id + * @since 7.0.0 + */ + public function setId($id); + + /** + * @param int $lastRun + * @since 7.0.0 + */ + public function setLastRun($lastRun); + + /** + * @param mixed $argument + * @since 7.0.0 + */ + public function setArgument($argument); + /** * Get the id of the background job * This id is determined by the job list when a job is added to the list