GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Application::doRun()   B
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 30
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 22
nc 3
nop 2
dl 0
loc 30
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * See class comment
4
 *
5
 * PHP Version 5
6
 *
7
 * @category   Netresearch
8
 * @package    Netresearch\Kite
9
 * @subpackage Console
10
 * @author     Christian Opitz <[email protected]>
11
 * @license    http://www.netresearch.de Netresearch Copyright
12
 * @link       http://www.netresearch.de
13
 */
14
15
namespace Netresearch\Kite\Console;
16
use Netresearch\Kite\Console\Command\LogCommand;
17
use Netresearch\Kite\Console\Output\ConsoleOutput;
18
use Netresearch\Kite\Console\Output\Output;
19
use Netresearch\Kite\Exception;
20
use Netresearch\Kite\Service\Config;
21
use Netresearch\Kite\Console\Command\JobCommand;
22
use Netresearch\Kite\Service\Factory;
23
use Symfony\Component\Console\Command\Command;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Input\InputOption;
26
use Symfony\Component\Console\Input\StringInput;
27
use Symfony\Component\Console\Output\OutputInterface;
28
use Symfony\Component\Process\Process;
29
30
/**
31
 * Kite application
32
 *
33
 * @category   Netresearch
34
 * @package    Netresearch\Kite
35
 * @subpackage Console
36
 * @author     Christian Opitz <[email protected]>
37
 * @license    http://www.netresearch.de Netresearch Copyright
38
 * @link       http://www.netresearch.de
39
 */
40
class Application extends \Symfony\Component\Console\Application
41
{
42
    /**
43
     * @var \Netresearch\Kite\Service\Config
44
     */
45
    protected $config;
46
47
    /**
48
     * @var Output
49
     */
50
    protected $output;
51
52
    /**
53
     * Application constructor.
54
     */
55
    public function __construct()
56
    {
57
        $this->output = new ConsoleOutput();
58
        $this->output->setTerminalDimensions($this->getTerminalDimensions());
59
60
        $this->loadConfig();
61
62
        parent::__construct('Kite');
63
    }
64
65
    /**
66
     * Load the configuration
67
     *
68
     * @return void
69
     */
70
    protected function loadConfig()
71
    {
72
        $this->config = new Config();
73
74
        $expectedFile = 'kite.php';
75
        $app = null;
76
        $indicators = [
77
            'TYPO3' => ['typo3conf', 'Kite.php'],
78
            'Magento' => ['app/etc', 'kite.php'],
79
        ];
80
        foreach ($indicators as $appName => $dirAndFile) {
81
            list($dir, $file) = $dirAndFile;
82
            if (is_dir($dir)) {
83
                $app = $appName;
84
                $expectedFile = $dir . '/' . $file;
85
                break;
86
            }
87
        }
88
89
        try {
90
            $this->config->loadConfigFile($expectedFile);
91
        } catch (\Exception $e) {
92
            if ($app) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $app of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
93
                $message = [
94
                    'You appear to be in a ' . $app . ' root directory but',
95
                    'there is no kite config file at the expected',
96
                    'location (' . $expectedFile . ').'
97
                ];
98
            } else {
99
                $message = [
100
                    'You are either not in an application root directory or',
101
                    'you have no appropriate config file yet.',
102
                    '',
103
                    'The config file path is expected to be:',
104
                ];
105
                foreach ($indicators as $appName => $dirAndFile) {
106
                    $message[] = '  - "' . implode('/', $dirAndFile) . '" for ' . $appName . ' applications or';
107
                }
108
                $message[] = '  - "' . $expectedFile . '" for any other application';
109
            }
110
            $lMax = 0;
111
            foreach ($message as $line) {
112
                if (($l = strlen($line)) > $lMax) {
113
                    $lMax = $l;
114
                }
115
            }
116
            $this->output->writeln('<warning>' . str_repeat(' ', $lMax + 4) . '</warning>');
117
            foreach ($message as $line) {
118
                $line = str_pad($line, $lMax + 2);
119
                $this->output->writeln("<warning>  $line</warning>");
120
            }
121
            $this->output->writeln('<warning>' . str_repeat(' ', $lMax + 4) . '</warning>');
122
        }
123
    }
124
125
    /**
126
     * Gets the help message.
127
     *
128
     * @return string A help message.
129
     */
130
    public function getHelp()
131
    {
132
        $help
133
            = " _  ___ _       \n"
134
            . "| |/ /_| |_ ___\n"
135
            . "| ' /| | __/ _ \\\n"
136
            . "| . \\| | |_| __/\n"
137
            . "|_|\\_|_|\\__\\___|\n\n"
138
            . $this->getLongVersion() . "\n\n"
139
            . $this->getSelfPackage()->description;
140
141
        return $help;
142
    }
143
144
    /**
145
     * Returns the long version of the application.
146
     *
147
     * @return string The long application version
148
     */
149
    public function getLongVersion()
150
    {
151
        $package = $this->getSelfPackage();
152
        $v = "<info>Kite</info> version <comment>{$package->version}</comment>";
153
        if (isset($package->source)) {
154
            $v .= " <comment>({$package->source->reference})</comment>";
155
        }
156
        $v .= ' ' . $package->time;
157
        return $v;
158
    }
159
160
    /**
161
     * Get package info from composer.lock
162
     *
163
     * @return object
164
     */
165
    protected function getSelfPackage()
166
    {
167
        static $package = null;
168
        if (!$package) {
169
            $files = [__DIR__ . '/../../../../composer/installed.json', __DIR__ . '/vendor/composer/installed.json'];
170
            foreach ($files as $file) {
171
                if (file_exists($file)) {
172
                    $installed = json_decode(file_get_contents($file));
173
                    foreach ($installed as $candidate) {
174
                        if (substr($candidate->name, -5) === '/kite') {
175
                            $package = $candidate;
176
                            break 2;
177
                        }
178
                    }
179
                }
180
            }
181
            if (!$package) {
182
                $kitePath = dirname(dirname(__DIR__));
183
                $process = new Process('git symbolic-ref -q --short HEAD || git describe --tags --exact-match; git rev-parse HEAD; git show -s --format=%ct HEAD', $kitePath);
184
                $process->run();
185
                if ($output = $process->getOutput()) {
186
                    $package = json_decode(file_get_contents($kitePath . '/composer.json'));
187
                    list($name, $revision, $tstamp) = explode("\n", trim($output), 3);
188
                    $package->version = preg_match('/^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9]+)?$/i', $name) ? $name : 'dev-' . $name;
189
                    $package->source = (object) ['reference' => $revision];
190
                    $package->time = date('Y-m-d H:i:s', $tstamp);
191
                } else {
192
                    throw new Exception('Could not determine self version');
193
                }
194
            }
195
        }
196
        return $package;
197
    }
198
199
    /**
200
     * Add workflow option
201
     *
202
     * @return \Symfony\Component\Console\Input\InputDefinition
203
     */
204
    protected function getDefaultInputDefinition()
0 ignored issues
show
Coding Style introduced by
getDefaultInputDefinition uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
205
    {
206
        $definition = parent::getDefaultInputDefinition();
207
        $definition->addOption(new InputOption('workflow', null, InputOption::VALUE_OPTIONAL, 'Run a workflow on the fly'));
208
209
        if (isset($_SERVER['HOME']) && is_writable($_SERVER['HOME'])) {
210
            $debugDir = $_SERVER['HOME'] . '/.kite/log';
211
        } else {
212
            $debugDir = false;
213
        }
214
        $definition->addOption(
215
            new InputOption(
216
                'debug-dir', null, InputOption::VALUE_OPTIONAL,
217
                "Path to directory to which to dump the debug output file",
218
                $debugDir
219
            )
220
        );
221
        return $definition;
222
    }
223
224
    /**
225
     * Runs the current application.
226
     *
227
     * @param InputInterface $input An Input instance
228
     *
229
     * @return int 0 if everything went fine, or an error code
230
     */
231
    public function run(InputInterface $input = null)
232
    {
233
        return parent::run($input, $this->output);
234
    }
235
236
237
    /**
238
     * Create job on the fly when workflow option is present
239
     *
240
     * @param InputInterface  $input  The input
241
     * @param OutputInterface $output The output
242
     *
243
     * @return int
244
     */
245
    public function doRun(InputInterface $input, OutputInterface $output)
246
    {
247
        if ($input->hasParameterOption('--workflow')) {
248
            $strInput = (string) $input;
249
            if ($this->getCommandName($input) === 'help') {
250
                $strInput = str_replace('help ', '', $strInput);
251
                $strInput .= ' --help';
252
            }
253
            $workflow = $input->getParameterOption('--workflow');
254
            $jobName = 'generic:workflow:' . $workflow;
255
            $this->config->configureJob($jobName, array('workflow' => $workflow));
0 ignored issues
show
Unused Code introduced by
The call to the method Netresearch\Kite\Service\Config::configureJob() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
256
            $command = new JobCommand($jobName, $this->config);
257
            $this->add($command);
258
259
            $parameterOption = '--workflow=' . $workflow;
260
            $input = new StringInput(
261
                rtrim(
262
                    $jobName . ' ' .
263
                    str_replace(
264
                        array(
265
                            $parameterOption . ' ',
266
                            ' ' . $parameterOption,
267
                            $parameterOption
268
                        ), '', $strInput
269
                    )
270
                )
271
            );
272
        }
273
        return parent::doRun($input, $output);
274
    }
275
276
277
    /**
278
     * Gets the default commands that should always be available.
279
     *
280
     * @return Command[] An array of default Command instances
281
     */
282
    protected function getDefaultCommands()
283
    {
284
        $commands = parent::getDefaultCommands();
285
        $commands[] = new LogCommand();
286
287
        foreach ($this->config->getJobConfiguration() as $name => $configuration) {
288
            $commands[] = new JobCommand($name, $this->config);
289
        }
290
291
        return $commands;
0 ignored issues
show
Best Practice introduced by
The expression return $commands; seems to be an array, but some of its elements' types (Netresearch\Kite\Console...sole\Command\JobCommand) are incompatible with the return type of the parent method Symfony\Component\Consol...ion::getDefaultCommands of type array<Symfony\Component\...le\Command\ListCommand>.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
292
    }
293
}
294
?>
295