Completed
Push — master ( 2ff2f4...64e7ee )
by Aydin
02:08
created

TimeServer   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 9
c 3
b 0
f 0
lcom 1
cbo 7
dl 0
loc 88
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getName() 0 4 1
A getDescription() 0 4 1
B check() 0 42 5
A getRandomPort() 0 4 1
1
<?php
2
3
namespace PhpSchool\LearnYouPhp\Exercise;
4
5
use Hoa\Core\Exception\Exception;
6
use PhpSchool\LearnYouPhp\TcpSocketFactory;
7
use PhpSchool\PhpWorkshop\Exercise\AbstractExercise;
8
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
9
use PhpSchool\PhpWorkshop\ExerciseCheck\SelfCheck;
10
use PhpSchool\PhpWorkshop\Result\Failure;
11
use PhpSchool\PhpWorkshop\Result\ResultInterface;
12
use PhpSchool\PhpWorkshop\Result\StdOutFailure;
13
use PhpSchool\PhpWorkshop\Result\Success;
14
use Psr\Http\Message\RequestInterface;
15
use Symfony\Component\Process\Process;
16
use Symfony\Component\Process\ProcessBuilder;
17
use Zend\Diactoros\Request;
18
19
/**
20
 * Class TimeServer
21
 * @package PhpSchool\LearnYouPhp\Exercise
22
 * @author Aydin Hassan <[email protected]>
23
 */
24
class TimeServer extends AbstractExercise implements ExerciseInterface, SelfCheck
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 string $fileName
59
     * @return ResultInterface
60
     */
61
    public function check($fileName)
62
    {
63
        $address    = '127.0.0.1';
64
        $port       = $this->getRandomPort();
65
66
        $cmd        = sprintf('%s %s %s', PHP_BINARY, $fileName, implode(' ', [$address, $port]));
67
        $process    = new Process($cmd, dirname($fileName));
68
        $process->start();
69
        
70
        //wait for server to boot
71
        usleep(100000);
72
        
73
        $client = $this->socketFactory->createClient($address, $port);
74
        
75
        try {
76
            $client->connect();
77
        } catch (Exception $e) {
78
            return Failure::fromNameAndReason($this->getName(), $e->getMessage());
79
        }
80
      
81
        $out = $client->readAll();
82
        
83
        //wait for shutdown
84
        usleep(100000);
85
        
86
        if ($process->isRunning()) {
87
            $process->stop();
88
        }
89
        
90
        if ($process->isSuccessful()) {
91
            $date = new \DateTime;
92
            
93
            //match the current date but any seconds
94
            //since we can't mock time in PHP easily
95
            if (!preg_match(sprintf('/^%s:([0-5][0-9]|60)\n$/', $date->format('Y-m-d H:i')), $out)) {
96
                return new StdOutFailure($this->getName(), $date->format("Y-m-d H:i:s\n"), $out);
97
            }
98
            return new Success($this->getName());
99
        }
100
101
        return new Failure($this->getName(), $process->getErrorOutput());
102
    }
103
104
    /**
105
     * @return int
106
     */
107
    private function getRandomPort()
108
    {
109
        return mt_rand(1025, 65535);
110
    }
111
}
112