Issues (125)

lib/Command/BackgroundCommand.php (4 issues)

1
<?php
2
/**
3
 * @copyright Copyright (c) 2017, Matias De lellis <[email protected]>
4
 * @copyright Copyright (c) 2018, Branko Kokanovic <[email protected]>
5
 *
6
 * @author Branko Kokanovic <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
namespace OCA\FaceRecognition\Command;
25
26
use OCP\Files\IRootFolder;
27
use OCP\App\IAppManager;
28
use OCP\IConfig;
29
use OCP\IUserManager;
30
31
use Symfony\Component\Console\Command\Command;
32
use Symfony\Component\Console\Input\InputArgument;
33
use Symfony\Component\Console\Input\InputOption;
34
use Symfony\Component\Console\Input\InputInterface;
35
use Symfony\Component\Console\Output\OutputInterface;
36
37
use OCA\FaceRecognition\Helper\CommandLock;
38
39
use OCA\FaceRecognition\BackgroundJob\BackgroundService;
40
41
class BackgroundCommand extends Command {
42
43
	/** @var BackgroundService */
44
	protected $backgroundService;
45
46
	/** @var IUserManager */
47
	protected $userManager;
48
49
	/**
50
	 * @param BackgroundService $backgroundService
51
	 * @param IUserManager $userManager
52
	 */
53
	public function __construct(BackgroundService $backgroundService,
54
	                            IUserManager      $userManager) {
55
		parent::__construct();
56
57
		$this->backgroundService = $backgroundService;
58
		$this->userManager = $userManager;
59
	}
60
61
	/**
62
	 * @return void
63
	 */
64
	protected function configure() {
65
		$this
66
			->setName('face:background_job')
67
			->setDescription('Equivalent of cron job to analyze images, extract faces and create clusters from found faces')
68
			->addOption(
69
				'user_id',
70
				'u',
71
				InputOption::VALUE_REQUIRED,
72
				'Analyze faces for the given user only. If not given, analyzes images for all users.',
73
				null
74
			)
75
			->addOption(
76
				'max_image_area',
77
				'M',
78
				InputOption::VALUE_REQUIRED,
79
				'Caps maximum area (in pixels^2) of the image to be fed to neural network, effectively lowering needed memory. ' .
80
				'Use this if face detection crashes randomly.'
81
			)
82
			->addOption(
83
				'sync-mode',
84
				null,
85
				InputOption::VALUE_NONE,
86
				'Execute all actions related to synchronizing the files. New users, shared or deleted files, etc.'
87
			)
88
			->addOption(
89
				'analyze-mode',
90
				null,
91
				InputOption::VALUE_NONE,
92
				'Execute only the action of analyzing the images to obtain the faces and their descriptors.'
93
			)
94
			->addOption(
95
				'cluster-mode',
96
				null,
97
				InputOption::VALUE_NONE,
98
				'Execute only the action of face clustering to get the people.'
99
			)
100
			->addOption(
101
				'defer-clustering',
102
				null,
103
				InputOption::VALUE_NONE,
104
				'Defer the face clustering at the end of the analysis to get persons in a simple execution of the command.'
105
			)
106
			->addOption(
107
				'timeout',
108
				't',
109
				InputOption::VALUE_REQUIRED,
110
				'Sets timeout in seconds for this command. Default is without timeout, e.g. command runs indefinitely.',
111
				0
112
			);
113
	}
114
115
	/**
116
	 * @param InputInterface $input
117
	 * @param OutputInterface $output
118
	 * @return int
119
	 */
120
	protected function execute(InputInterface $input, OutputInterface $output) {
121
		$this->backgroundService->setLogger($output);
122
123
		// Extract user, if any
124
		//
125
		$userId = $input->getOption('user_id');
126
		$user = null;
127
128
		if (!is_null($userId)) {
129
			$user = $this->userManager->get($userId);
0 ignored issues
show
It seems like $userId can also be of type string[]; however, parameter $uid of OCP\IUserManager::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

129
			$user = $this->userManager->get(/** @scrutinizer ignore-type */ $userId);
Loading history...
130
			if ($user === null) {
131
				throw new \InvalidArgumentException("User with id <$userId> in unknown.");
132
			}
133
		}
134
135
		// Extract timeout
136
		//
137
		$timeout = $input->getOption('timeout');
138
		if (!is_null($timeout)) {
139
			if ($timeout < 0) {
140
				throw new \InvalidArgumentException("Timeout must be positive value in seconds.");
141
			}
142
		} else {
143
			$timeout = 0;
144
		}
145
146
		// Extract max image area
147
		//
148
		$maxImageArea = $input->getOption('max_image_area');
149
		if (!is_null($maxImageArea)) {
150
			$maxImageArea = intval($maxImageArea);
151
152
			if ($maxImageArea === 0) {
153
				throw new \InvalidArgumentException("Max image area must be positive number.");
154
			}
155
156
			if ($maxImageArea < 0) {
157
				throw new \InvalidArgumentException("Max image area must be positive value.");
158
			}
159
		}
160
161
		// Extract mode from options
162
		//
163
		$mode = 'default-mode';
164
		if ($input->getOption('sync-mode')) {
165
			$mode = 'sync-mode';
166
		} else if ($input->getOption('analyze-mode')) {
167
			$mode = 'analyze-mode';
168
		} else if ($input->getOption('cluster-mode')) {
169
			$mode = 'cluster-mode';
170
		} else if ($input->getOption('defer-clustering')) {
171
			$mode = 'defer-mode';
172
		}
173
174
		// Extract verbosity (for command, we don't need this, but execute asks for it, if running from cron job).
175
		//
176
		$verbose = $input->getOption('verbose');
177
178
		// In image analysis mode it run in parallel.
179
		// In any other case acquire lock so that only one background task can run
180
		//
181
		$globalLock = ($mode != 'analyze-mode');
182
		if ($globalLock) {
183
			$lock = CommandLock::Lock('face:background_job');
0 ignored issues
show
Are you sure the assignment to $lock is correct as OCA\FaceRecognition\Help...('face:background_job') targeting OCA\FaceRecognition\Helper\CommandLock::lock() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
184
			if (!$lock) {
0 ignored issues
show
$lock is of type null, thus it always evaluated to false.
Loading history...
185
				$output->writeln("Another task ('". CommandLock::IsLockedBy().  "') is already running that prevents it from continuing.");
186
				return 1;
187
			}
188
		}
189
190
		// Main thing
191
		//
192
		$this->backgroundService->execute($timeout, $verbose, $user, $maxImageArea, $mode);
193
194
		// Release obtained lock
195
		//
196
		if ($globalLock) {
0 ignored issues
show
The condition $globalLock is always false.
Loading history...
197
			CommandLock::Unlock($lock);
198
		}
199
200
		return 0;
201
	}
202
}
203