Completed
Push — issues ( f063a7 )
by Arnaud
04:03
created

Serve   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 13
dl 0
loc 113
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A setUpServer() 0 20 4
A tearDownServer() 0 12 2
B processCommand() 0 63 9
1
<?php
2
/*
3
 * This file is part of the PHPoole package.
4
 *
5
 * Copyright (c) Arnaud Ligny <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace PHPoole\Command;
12
13
use PHPoole\Util\Plateform;
14
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
15
use Symfony\Component\Filesystem\Filesystem;
16
use Symfony\Component\Finder\Finder;
17
use Symfony\Component\Process\Exception\ProcessFailedException;
18
use Symfony\Component\Process\Process;
19
use Yosymfony\ResourceWatcher\Crc32ContentHash;
20
use Yosymfony\ResourceWatcher\ResourceCacheMemory;
21
use Yosymfony\ResourceWatcher\ResourceWatcher;
22
23
class Serve extends AbstractCommand
24
{
25
    /**
26
     * @var bool
27
     */
28
    protected $watch;
29
    /**
30
     * @var bool
31
     */
32
    protected $browser;
33
    /**
34
     * @var Filesystem
35
     */
36
    protected $fileSystem;
37
38
    public function processCommand()
39
    {
40
        $this->watch = $this->getRoute()->getMatchedParam('watch', false);
41
        $this->browser = $this->getRoute()->getMatchedParam('browser', false);
42
        $this->fileSystem = new Filesystem();
43
44
        $this->setUpServer();
45
        $command = sprintf(
46
            'php -S %s:%d -t %s %s',
47
            'localhost',
48
            '8000',
49
            $this->getPath().'/'.$this->getPHPoole()->getConfig()->get('output.dir'),
50
            sprintf('%s/.phpoole/router.php', $this->getPath())
51
        );
52
53
        $this->wlAnnonce(sprintf('Starting server (http://%s:%d)...', 'localhost', '8000'));
54
        $process = new Process($command);
55
        if (!$process->isStarted()) {
56
            // write changes cache
57
            if ($this->watch) {
58
                $finder = new Finder();
59
                $finder->files()
60
                    ->name('*.md')
61
                    ->name('*.twig')
62
                    ->in([
63
                        $this->getPath().'/'.$this->getPHPoole()->getConfig()->get('content.dir'),
64
                        $this->getPath().'/'.$this->getPHPoole()->getConfig()->get('layouts.dir'),
65
                    ]);
66
                if (is_dir($this->getPath().'/'.$this->getPHPoole()->getConfig()->get('themes.dir'))) {
67
                    $finder->in($this->getPath().'/'.$this->getPHPoole()->getConfig()->get('themes.dir'));
68
                }
69
                $hashContent = new Crc32ContentHash();
70
                $resourceCache = new ResourceCacheMemory();
71
                $resourceWatcher = new ResourceWatcher($resourceCache, $finder, $hashContent);
72
                $resourceWatcher->initialize();
73
                $this->fileSystem->dumpFile($this->getPath().'/.phpoole/watch.flag', '');
74
            }
75
            // start server
76
            try {
77
                $process->start();
78
                if ($this->browser) {
79
                    Plateform::openBrowser('http://localhost:8000');
80
                }
81
                while ($process->isRunning()) {
82
                    // watch changes?
83
                    if ($this->watch) {
84
                        $result = $resourceWatcher->findChanges();
0 ignored issues
show
Bug introduced by
The variable $resourceWatcher does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
85
                        if ($result->hasChanges()) {
86
                            // re-generate
87
                            $this->wlAlert('Changes detected!');
88
                            $callable = new Build($this->getRoute(), $this->getConsole());
0 ignored issues
show
Unused Code introduced by
The call to Build::__construct() has too many arguments starting with $this->getRoute().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
89
                            $callable($this->getRoute(), $this->getConsole());
90
                        }
91
                    }
92
                    usleep(1000000); // 1 s
93
                }
94
            } catch (ProcessFailedException $e) {
95
                $this->tearDownServer();
96
                echo $e->getMessage();
97
                exit(2);
98
            }
99
        }
100
    }
101
102
    public function setUpServer()
103
    {
104
        try {
105
            $root = __DIR__.'/../../';
106
            if (Plateform::isPhar()) {
107
                $root = Plateform::getPharPath().'/';
108
            }
109
            $this->fileSystem->copy($root.'res/router.php', $this->getPath().'/.phpoole/router.php', true);
110
            $this->fileSystem->copy($root.'res/livereload.js', $this->getPath().'/.phpoole/livereload.js', true);
111
            $this->fileSystem->dumpFile($this->getPath().'/.phpoole/baseurl', $this->getPHPoole()->getConfig()->get('site.baseurl'));
112
        } catch (IOExceptionInterface $e) {
113
            echo 'An error occurred while copying file at '.$e->getPath().PHP_EOL;
114
            echo $e->getMessage().PHP_EOL;
115
            exit(2);
116
        }
117
        if (!is_file(sprintf('%s/.phpoole/router.php', $this->getPath()))) {
118
            $this->wlError('Router not found');
119
            exit(2);
120
        }
121
    }
122
123
    public function tearDownServer()
124
    {
125
        try {
126
            $this->fileSystem->remove([
0 ignored issues
show
Documentation introduced by
array($this->getPath() .... . '/.phpoole/baseurl') is of type array<integer,string,{"0..."string","2":"string"}>, but the function expects a string|object<Symfony\Co...nt\Filesystem\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
127
                $this->getPath().'/.phpoole/router.php',
128
                $this->getPath().'/.phpoole/livereload.js',
129
                $this->getPath().'/.phpoole/baseurl',
130
            ]);
131
        } catch (IOExceptionInterface $e) {
132
            echo $e->getMessage().PHP_EOL;
133
        }
134
    }
135
}
136