TimeServer::getRandomPort()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace PhpSchool\LearnYouPhp\Exercise;
4
5
use Hoa\Socket\Exception\Exception;
6
use PhpSchool\LearnYouPhp\TcpSocketFactory;
7
use PhpSchool\PhpWorkshop\Event\CliExecuteEvent;
8
use PhpSchool\PhpWorkshop\Exercise\AbstractExercise;
9
use PhpSchool\PhpWorkshop\Exercise\CliExercise;
10
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
11
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
12
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
13
use PhpSchool\PhpWorkshop\Output\OutputInterface;
14
use PhpSchool\PhpWorkshop\Result\ComparisonFailure;
15
use PhpSchool\PhpWorkshop\Result\Failure;
16
use PhpSchool\PhpWorkshop\Result\StdOutFailure;
17
use PhpSchool\PhpWorkshop\Result\Success;
18
19
/**
20
 * Class TimeServer
21
 * @package PhpSchool\LearnYouPhp\Exercise
22
 * @author Aydin Hassan <[email protected]>
23
 */
24
class TimeServer extends AbstractExercise implements ExerciseInterface, CliExercise
25
{
26
27
    /**
28
     * @var TcpSocketFactory
29
     */
30
    private $socketFactory;
31
32
    /**
33
     * TimeServer constructor.
34
     * @param TcpSocketFactory $socketFactory
35
     */
36
    public function __construct(TcpSocketFactory $socketFactory)
37
    {
38
        $this->socketFactory = $socketFactory;
39
    }
40
    
41
    /**
42
     * @return string
43
     */
44
    public function getName()
45
    {
46
        return 'Time Server';
47
    }
48
49
    /**
50
     * @return string
51
     */
52
    public function getDescription()
53
    {
54
        return 'Build a Time Server!';
55
    }
56
57
    /**
58
     * @param ExerciseDispatcher $exerciseDispatcher
59
     */
60
    public function configure(ExerciseDispatcher $exerciseDispatcher)
61
    {
62
        $eventDispatcher = $exerciseDispatcher->getEventDispatcher();
63
64
        $appendArgsListener = function (CliExecuteEvent $event) {
65
            $event->appendArg('127.0.0.1');
66
            $event->appendArg($this->getRandomPort());
67
        };
68
69
        $eventDispatcher->listen('cli.verify.reference-execute.pre', $appendArgsListener);
70
        $eventDispatcher->listen('cli.verify.student-execute.pre', $appendArgsListener);
71
        $eventDispatcher->listen('cli.run.student-execute.pre', $appendArgsListener);
72
73
        $eventDispatcher->listen('cli.verify.reference.executing', function (CliExecuteEvent $event) {
74
            $args   = $event->getArgs()->getArrayCopy();
75
            $client = $this->socketFactory->createClient(...$args);
0 ignored issues
show
Bug introduced by
The call to createClient() misses a required argument $port.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
$args is of type array, but the function expects a string.

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...
76
77
            //wait for server to boot
78
            usleep(100000);
79
80
            $client->connect();
81
            $client->readAll();
82
83
            //wait for shutdown
84
            usleep(100000);
85
        });
86
87
        $eventDispatcher->insertVerifier('cli.verify.student.executing', function (CliExecuteEvent $event) {
88
            $args   = $event->getArgs()->getArrayCopy();
89
            $client = $this->socketFactory->createClient(...$args);
0 ignored issues
show
Bug introduced by
The call to createClient() misses a required argument $port.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
$args is of type array, but the function expects a string.

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...
90
91
            //wait for server to boot
92
            usleep(100000);
93
94
            try {
95
                $client->connect();
96
            } catch (Exception $e) {
97
                return Failure::fromNameAndReason($this->getName(), $e->getMessage());
98
            }
99
100
            $out = $client->readAll();
101
102
            //wait for shutdown
103
            usleep(100000);
104
105
            $date = new \DateTime;
106
107
            //match the current date but any seconds
108
            //since we can't mock time in PHP easily
109
            if (!preg_match(sprintf('/^%s:([0-5][0-9]|60)\n$/', $date->format('Y-m-d H:i')), $out)) {
110
                return ComparisonFailure::fromNameAndValues($this->getName(), $date->format("Y-m-d H:i:s\n"), $out);
111
            }
112
            return new Success($this->getName());
113
        });
114
115
        $eventDispatcher->listen('cli.run.student.executing', function (CliExecuteEvent $event) {
116
            /** @var OutputInterface $output */
117
            $output = $event->getParameter('output');
118
            $args   = $event->getArgs()->getArrayCopy();
119
            $client = $this->socketFactory->createClient(...$args);
0 ignored issues
show
Bug introduced by
The call to createClient() misses a required argument $port.

This check looks for function calls that miss required arguments.

Loading history...
Documentation introduced by
$args is of type array, but the function expects a string.

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...
120
121
            //wait for server to boot
122
            usleep(100000);
123
124
            $client->connect();
125
            $out = $client->readAll();
126
127
            //wait for shutdown
128
            usleep(100000);
129
130
            $output->write($out);
131
        });
132
    }
133
134
    /**
135
     * @return string
136
     */
137
    private function getRandomPort()
138
    {
139
        return (string) mt_rand(1025, 65535);
140
    }
141
142
    /**
143
     * @return ExerciseType
144
     */
145
    public function getType()
146
    {
147
        return ExerciseType::CLI();
148
    }
149
150
    /**
151
     * @return string[]
152
     */
153
    public function getArgs()
154
    {
155
        return [];
156
    }
157
}
158