Run::run()   B
last analyzed

Complexity

Conditions 9
Paths 30

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 45
rs 7.6444
c 0
b 0
f 0
cc 9
nc 30
nop 0
1
<?php
2
/**
3
 * @author Threema GmbH
4
 * @copyright Copyright (c) 2015-2016 Threema GmbH
5
 */
6
7
8
namespace Threema\Console;
9
10
use Threema\Console\Command\Base;
11
use Threema\Console\Command\Capability;
12
use Threema\Console\Command\Decrypt;
13
use Threema\Console\Command\DerivePublicKey;
14
use Threema\Console\Command\Encrypt;
15
use Threema\Console\Command\GenerateKeyPair;
16
use Threema\Console\Command\HashEmail;
17
use Threema\Console\Command\HashPhone;
18
use Threema\Console\Command\LookupIdByEmail;
19
use Threema\Console\Command\LookupIdByPhoneNo;
20
use Threema\Console\Command\LookupPublicKeyById;
21
use Threema\Console\Command\ReceiveMessage;
22
use Threema\Console\Command\SendE2EFile;
23
use Threema\Console\Command\SendE2EImage;
24
use Threema\Console\Command\SendE2EText;
25
use Threema\Console\Command\SendSimple;
26
use Threema\Console\Command\Credits;
27
use Threema\Console\Command\FeatureLevel;
28
use Threema\Core\Exception;
29
use Threema\MsgApi\PublicKeyStore;
30
use Threema\MsgApi\Tools\CryptTool;
31
32
/**
33
 * Handling the console run stuff
34
 *
35
 * @package Threema\Console
36
 */
37
class Run {
38
	/**
39
	 * @var array
40
	 */
41
	private $arguments = array();
42
43
	/**
44
	 * @var \Threema\Console\Command\Base[]
45
	 */
46
	private $commands = array();
47
48
	/**
49
	 * @var string
50
	 */
51
	private $scriptName;
52
53
	/**
54
	 * @var PublicKeyStore
55
	 */
56
	private $publicKeyStore;
57
58
	/**
59
	 * @param array $arguments
60
	 * @param PublicKeyStore $publicKeyStore
61
	 */
62
	public function __construct(array $arguments, PublicKeyStore $publicKeyStore) {
63
		$this->arguments = $arguments;
64
		$this->scriptName = basename(array_shift($this->arguments));
65
		$this->publicKeyStore = $publicKeyStore;
66
67
		$this->registerSubject('Local operations (no network communication)');
68
		$this->register('-e', new Encrypt());
69
		$this->register('-D', new Decrypt());
70
		$this->register(array('-h', '-e'), new HashEmail());
71
		$this->register(array('-h', '-p'), new HashPhone());
72
		$this->register('-g', new GenerateKeyPair());
73
		$this->register('-d', new DerivePublicKey());
74
		$this->register('-v', new FeatureLevel());
75
76
		$this->registerSubject('Network operations');
77
		//network operations
78
		$this->register('-s', new SendSimple($this->publicKeyStore));
79
		$this->register('-S', new SendE2EText($this->publicKeyStore));
80
		$this->register(array('-S', '-i'), new SendE2EImage($this->publicKeyStore));
81
		$this->register(array('-S', '-f'), new SendE2EFile($this->publicKeyStore));
82
		$this->register(array('-l', '-e'), new LookupIdByEmail($this->publicKeyStore));
83
		$this->register(array('-l', '-p'), new LookupIdByPhoneNo($this->publicKeyStore));
84
		$this->register(array('-l', '-k'), new LookupPublicKeyById($this->publicKeyStore));
85
		$this->register(array('-c'), new Capability($this->publicKeyStore));
86
		$this->register(array('-r'), new ReceiveMessage($this->publicKeyStore));
87
		$this->register(array('-C'), new Credits($this->publicKeyStore));
88
	}
89
90
	private function register($argumentKey, Base $command) {
91
		if(is_scalar($argumentKey)) {
92
			$argumentKey = array($argumentKey);
93
		}
94
95
		//check for existing commands with the same arguments
96
		foreach($this->commands as $commandValues) {
97
			$ex = $commandValues[0];
98
			if(null !== $ex && is_array($ex)) {
99
				if(count($ex) == count($argumentKey)
100
					&& count(array_diff($ex, $argumentKey)) == 0) {
101
					throw new Exception('arguments '.implode($argumentKey).' already used');
102
				}
103
			}
104
		}
105
		$this->commands[] = array($argumentKey, $command);
106
		return $this;
107
	}
108
109
	private function registerSubject($name) {
110
		$this->commands[] = $name;
111
	}
112
113
	public function run() {
114
		$found = null;
115
		$argumentLength = 0;
116
117
		//find the correct command by arguments and arguments count
118
		foreach($this->commands as $data) {
119
			if(is_scalar($data)) {
120
				continue;
121
			}
122
123
			list($keys, $command) = $data;
124
			if(array_slice($this->arguments, 0, count($keys)) == $keys) {
125
				$argCount = count($this->arguments)-count($keys);
126
127
				/** @noinspection PhpUndefinedMethodInspection */
128
				if($argCount >= $command->getRequiredArgumentCount()
129
					&& $argCount <= $command->getAllArgumentsCount()) {
130
					$found = $command;
131
					$argumentLength = count($keys);
132
					break;
133
				}
134
			}
135
		}
136
137
		if($argumentLength > 0) {
138
			array_splice($this->arguments, 0, $argumentLength);
139
		}
140
141
		if(null === $found) {
142
			$this->help();
143
		}
144
		else {
145
146
147
			try {
148
				$found->run($this->arguments);
149
			}
150
			catch(Exception $x) {
151
				Common::l();
152
				Common::e('ERROR: '.$x->getMessage());
153
				Common::e(get_class($x));
154
				Common::l();
155
			}
156
		}
157
	}
158
159
	private function help() {
160
		$defaultCryptTool = CryptTool::getInstance();
161
162
		Common::l();
163
		Common::l('Threema PHP MsgApi Tool');
164
		Common::l('Version: '.MSGAPI_SDK_VERSION);
165
		Common::l('Feature level: '.MSGAPI_SDK_FEATURE_LEVEL);
166
		Common::l('CryptTool: '.$defaultCryptTool->getName().' ('.$defaultCryptTool->getDescription().')');
167
		Common::l(str_repeat('.', 40));
168
		Common::l();
169
		foreach($this->commands as $data) {
170
			if(is_scalar($data)) {
171
				Common::l($data);
172
				Common::l(str_repeat('-', strlen($data)));
173
				Common::l();
174
			}
175
			else {
176
				list($key, $command) = $data;
177
				Common::ln($this->scriptName.' '."\033[1;33m".implode(' ', $key)."\033[0m".' '.$command->help());
178
				Common::l();
179
				/** @noinspection PhpUndefinedMethodInspection */
180
				Common::l($command->description(), 1);
181
				Common::l();
182
			}
183
		}
184
	}
185
186
	public function writeHelp(\Closure $writer) {
187
		if(null !== $writer) {
188
189
			foreach($this->commands as $data) {
190
				if(is_scalar($data)) {
191
					$writer->__invoke($data, null, null, false);
192
				}
193
				else {
194
					list($key, $command) = $data;
195
					$writer->__invoke($command->subject(false), $this->scriptName.' '.implode(' ', $key).' '.$command->help(false), $command->description(), true);
196
				}
197
			}
198
		}
199
	}
200
}
201