Completed
Push — master ( 8dd5e5...8b2998 )
by Sebastian
02:55
created

Cmd::createConfiguration()   C

Complexity

Conditions 7
Paths 32

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 1
Metric Value
c 6
b 0
f 1
dl 0
loc 34
rs 6.7272
cc 7
eloc 20
nc 32
nop 0
1
<?php
2
/**
3
 * phpbu
4
 *
5
 * Copyright (c) 2014 - 2015 Sebastian Feldmann <[email protected]>
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 *
25
 * @package    phpbu
26
 * @author     Sebastian Feldmann <[email protected]>
27
 * @copyright  Sebastian Feldmann
28
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
29
 * @link       http://phpbu.de/
30
 * @since      Class available since Release 1.0.0
31
 */
32
namespace phpbu\App;
33
34
use Phar;
35
use phpbu\App\Cmd\Args;
36
use phpbu\App\Util\Arr;
37
38
/**
39
 * Main application class.
40
 *
41
 * @package    phpbu
42
 * @author     Sebastian Feldmann <[email protected]>
43
 * @copyright  Sebastian Feldmann <[email protected]>
44
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
45
 * @link       http://phpbu.de/
46
 * @since      Class available since Release 1.0.0
47
 */
48
class Cmd
49
{
50
    const EXIT_SUCCESS   = 0;
51
    const EXIT_FAILURE   = 1;
52
    const EXIT_EXCEPTION = 2;
53
54
    /**
55
     * Ascii-Art app logo
56
     *
57
     * @var string
58
     */
59
    private static $logo = '             __          __
60
      ____  / /_  ____  / /_  __  __
61
     / __ \/ __ \/ __ \/ __ \/ / / /
62
    / /_/ / / / / /_/ / /_/ / /_/ /
63
   / .___/_/ /_/ .___/_.___/\__,_/
64
  /_/         /_/
65
';
66
67
    /**
68
     * Is cmd executed from phar.
69
     *
70
     * @var boolean
71
     */
72
    private $isPhar;
73
74
    /**
75
     * Is version string printed already.
76
     *
77
     * @var boolean
78
     */
79
    private $isVersionStringPrinted = false;
80
81
    /**
82
     * List of given arguments
83
     *
84
     * @var array
85
     */
86
    private $arguments;
87
88
    /**
89
     * Runs the application.
90
     *
91
     * @param array $args
92
     */
93
    public function run(array $args)
94
    {
95
        $this->isPhar = defined('__PHPBU_PHAR__');
96
        $this->handleOpt($args);
97
        $this->findConfiguration();
98
99
        $ret    = self::EXIT_FAILURE;
100
        $runner = new Runner(new Factory());
101
102
        try {
103
            $result = $runner->run($this->createConfiguration());
104
105
            if ($result->wasSuccessful()) {
106
                $ret = self::EXIT_SUCCESS;
107
            } elseif ($result->errorCount() > 0) {
108
                $ret = self::EXIT_EXCEPTION;
109
            }
110
        } catch (\Exception $e) {
111
            echo $e->getMessage() . PHP_EOL;
112
            $ret = self::EXIT_EXCEPTION;
113
        }
114
115
        exit($ret);
116
    }
117
118
    /**
119
     * Check arguments and load configuration file.
120
     *
121
     * @param array $args
122
     */
123
    protected function handleOpt(array $args)
124
    {
125
        try {
126
            $parser  = new Args($this->isPhar);
127
            $options = $parser->getOptions($args);
128
            $this->handleArgs($options);
129
        } catch (Exception $e) {
130
            $this->printError($e->getMessage(), true);
131
        }
132
    }
133
134
    /**
135
     * Handle the parsed command line options
136
     *
137
     * @param  array $options
138
     * @return void
139
     */
140
    protected function handleArgs(array $options)
141
    {
142
        foreach ($options as $option => $argument) {
143
            switch ($option) {
144
                case '--bootstrap':
145
                    $this->arguments['bootstrap'] = $argument;
146
                    break;
147
                case '--colors':
148
                    $this->arguments['colors'] = $argument;
149
                    break;
150
                case '--configuration':
151
                    $this->arguments['configuration'] = $argument;
152
                    break;
153
                case '--debug':
154
                    $this->arguments['debug'] = $argument;
155
                    break;
156
                case '-h':
157
                case '--help':
158
                    $this->printHelp();
159
                    exit(self::EXIT_SUCCESS);
160
                case 'include-path':
161
                    $this->arguments['include-path'] = $argument;
162
                    break;
163
                case '--selfupdate':
164
                case '--self-update':
165
                    $this->handleSelfUpdate();
166
                    break;
167
                case '--simulate':
168
                    $this->arguments['simulate'] = $argument;
169
                    break;
170
                case '-v':
171
                case '--verbose':
172
                    $this->arguments['verbose'] = true;
173
                    break;
174
                case '-V':
175
                case '--version':
176
                    $this->printVersionString();
177
                    exit(self::EXIT_SUCCESS);
178
            }
179
        }
180
    }
181
182
    /**
183
     * Try to find the configuration file.
184
     */
185
    protected function findConfiguration()
186
    {
187
        // check configuration argument
188
        // if configuration argument is a directory
189
        // check for default configuration files 'phpbu.xml' and 'phpbu.xml.dist'
190
        if (isset($this->arguments['configuration']) && is_file($this->arguments['configuration'])) {
191
            $this->arguments['configuration'] = realpath($this->arguments['configuration']);
192
        } elseif (isset($this->arguments['configuration']) && is_dir($this->arguments['configuration'])) {
193
            $this->findConfigurationInDir();
194
        } elseif (!isset($this->arguments['configuration'])) {
195
            // no configuration argument search for default configuration files
196
            // 'phpbu.xml' and 'phpbu.xml.dist' in current working directory
197
            $this->findConfigurationDefault();
198
        }
199
        // no config found, exit with some help output
200
        if (!isset($this->arguments['configuration'])) {
201
            $this->printLogo();
202
            $this->printHelp();
203
            exit(self::EXIT_EXCEPTION);
204
        }
205
    }
206
207
    /**
208
     * Check directory for default configuration files phpbu.xml, phpbu.xml.dist.
209
     *
210
     * @return void
211
     */
212
    protected function findConfigurationInDir()
213
    {
214
        $configurationFile = $this->arguments['configuration'] . '/phpbu.xml';
215
216
        if (file_exists($configurationFile)) {
217
            $this->arguments['configuration'] = realpath($configurationFile);
218
        } elseif (file_exists($configurationFile . '.dist')) {
219
            $this->arguments['configuration'] = realpath($configurationFile . '.dist');
220
        }
221
    }
222
223
    /**
224
     * Check default configuration files phpbu.xml, phpbu.xml.dist in current working directory.
225
     *
226
     * @return void
227
     */
228
    protected function findConfigurationDefault()
229
    {
230
        if (file_exists('phpbu.xml')) {
231
            $this->arguments['configuration'] = realpath('phpbu.xml');
232
        } elseif (file_exists('phpbu.xml.dist')) {
233
            $this->arguments['configuration'] = realpath('phpbu.xml.dist');
234
        }
235
    }
236
237
    /**
238
     * Create a application configuration.
239
     *
240
     * @return \phpbu\App\Configuration
241
     */
242
    protected function createConfiguration()
243
    {
244
        $configLoader  = Configuration\Loader\Factory::createLoader($this->arguments['configuration']);
245
        $configuration = $configLoader->getConfiguration();
246
247
        // command line arguments overrule the config file settings
248
        if (Arr::getValue($this->arguments, 'verbose') === true) {
249
            $configuration->setVerbose(true);
250
        }
251
        if (Arr::getValue($this->arguments, 'colors') === true) {
252
            $configuration->setColors(true);
253
        }
254
        if (Arr::getValue($this->arguments, 'debug') === true) {
255
            $configuration->setDebug(true);
256
        }
257
        if (Arr::getValue($this->arguments, 'simulate') === true) {
258
            $configuration->setSimulate(true);
259
        }
260
261
        $bootstrap = Arr::getValue($this->arguments, 'bootstrap');
262
        if (!empty($bootstrap)) {
263
            $configuration->setBootstrap($bootstrap);
264
        }
265
266
        // add a cli printer for some output
267
        $configuration->addLogger(
268
            new Result\PrinterCli(
269
                $configuration->getVerbose(),
270
                $configuration->getColors(),
271
                ($configuration->getDebug() || $configuration->isSimulation())
272
            )
273
        );
274
        return $configuration;
275
    }
276
277
    /**
278
     * Handle the phar self-update.
279
     */
280
    protected function handleSelfUpdate()
281
    {
282
        $this->printVersionString();
283
284
        $remoteFilename = 'http://phar.phpbu.de/phpbu.phar';
285
        $localFilename  = realpath($_SERVER['argv'][0]);
286
        $tempFilename   = basename($localFilename, '.phar') . '-temp.phar';
287
288
        echo 'Updating the phpbu PHAR ... ';
289
290
        $old  = error_reporting(0);
291
        $phar = file_get_contents($remoteFilename);
292
        error_reporting($old);
293
        if (!$phar) {
294
            echo ' failed' . PHP_EOL . 'Could not reach phpbu update site' . PHP_EOL;
295
            exit(self::EXIT_EXCEPTION);
296
        }
297
        file_put_contents($tempFilename, $phar);
298
299
        chmod($tempFilename, 0777 & ~umask());
300
301
        // check downloaded phar
302
        try {
303
            $phar = new Phar($tempFilename);
304
            unset($phar);
305
            // replace current phar with the new one
306
            rename($tempFilename, $localFilename);
307
        } catch (Exception $e) {
308
            // cleanup crappy phar
309
            unlink($tempFilename);
310
            echo 'failed' . PHP_EOL . $e->getMessage() . PHP_EOL;
311
            exit(self::EXIT_EXCEPTION);
312
        }
313
314
        echo 'done' . PHP_EOL;
315
        exit(self::EXIT_SUCCESS);
316
    }
317
318
    /**
319
     * Shows the current application version.
320
     */
321
    private function printVersionString()
322
    {
323
        if ($this->isVersionStringPrinted) {
324
            return;
325
        }
326
327
        echo Version::getVersionString() . PHP_EOL;
328
        $this->isVersionStringPrinted = true;
329
    }
330
331
    /**
332
     * Show the phpbu logo
333
     */
334
    protected function printLogo()
335
    {
336
        echo self::$logo . PHP_EOL;
337
    }
338
339
    /**
340
     * Show the help message.
341
     */
342
    protected function printHelp()
343
    {
344
        $this->printVersionString();
345
        echo <<<EOT
346
347
Usage: phpbu [option]
348
349
  --bootstrap=<file>     A "bootstrap" PHP file that is included before the backup.
350
  --configuration=<file> A phpbu xml config file.
351
  --colors               Use colors in output.
352
  --debug                Display debugging information during backup generation.
353
  -h, --help             Prints this usage information.
354
  -v, --verbose          Output more verbose information.
355
  -V, --version          Output version information and exit.
356
357
EOT;
358
        if ($this->isPhar) {
359
            echo '  --self-update          Update phpbu to the latest version.' . PHP_EOL;
360
        }
361
    }
362
363
    /**
364
     * Shows some given error message.
365
     *
366
     * @param string $message
367
     * @param bool   $hint
368
     */
369
    private function printError($message, $hint = false)
370
    {
371
        $help = $hint ? ', use "phpbu -h" for help' : '';
372
        $this->printVersionString();
373
        echo $message . $help . PHP_EOL;
374
        exit(self::EXIT_EXCEPTION);
375
    }
376
377
    /**
378
     * Main method, is called by phpbu command and the phar file.
379
     */
380
    public static function main()
381
    {
382
        $app = new static();
383
        $app->run($_SERVER['argv']);
384
    }
385
}
386