Completed
Push — master ( 7d6afc...af3c22 )
by Douglas
02:06
created

FileRobotStore::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
/**
4
 * (c) 2018 Douglas Reith.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
declare(strict_types=1);
10
11
namespace Reith\ToyRobot\Infrastructure\Persistence;
12
13
use Psr\Log\LoggerInterface;
14
use Reith\ToyRobot\Domain\Robot\Robot;
15
16
class FileRobotStore implements RobotStoreInterface
17
{
18
    private const FILE_VERSION = '001';
19
20
    private static $store;
21
22
    private $file;
23
24
    private $logger;
25
26
    /**
27
     * __construct.
28
     *
29
     * @param \SplFileObject $file
30
     * @param LoggerInterface|null $logger
31
     */
32 1
    private function __construct(\SplFileObject $file, ?LoggerInterface $logger = null)
33
    {
34 1
        $this->file = $file;
35 1
        $this->logger = $logger;
36 1
    }
37
38
    public function __destruct()
39
    {
40
        $this->file = null;
41
    }
42
43
    /**
44
     * @param string               $basePath
45
     * @param LoggerInterface|null $logger
46
     *
47
     * @return RobotStoreInterface
48
     */
49 3
    public static function getStore(string $basePath, ?LoggerInterface $logger = null): RobotStoreInterface
50
    {
51
        // Ensure the same store is used everywhere
52 3
        if (!self::$store) {
53 1
            self::$store = self::createStore($basePath, $logger);
54
        }
55
56 3
        return self::$store;
57
    }
58
59
    /**
60
     * @param string               $basePath
61
     * @param LoggerInterface|null $logger
62
     *
63
     * @return RobotStoreInterface
64
     */
65 1
    private static function createStore(string $basePath, ?LoggerInterface $logger): RobotStoreInterface
66
    {
67 1
        $baseDir = $basePath . DIRECTORY_SEPARATOR . 'robotstore';
68
69 1
        if (false === file_exists($baseDir)) {
70 1
            mkdir($baseDir, 0644, true);
71
        }
72
73 1
        $fileName = $baseDir . DIRECTORY_SEPARATOR . self::FILE_VERSION . '-robot.txt';
74
75 1
        if (false === file_exists($fileName)) {
76 1
            touch($fileName);
77
        }
78
79
        // w+ - for reading and writing
80 1
        return new static(new \SplFileObject($fileName, 'w+'), $logger);
81
    }
82
83
    /**
84
     * @return Robot|null
85
     */
86
    public function getRobot(): ?Robot
87
    {
88
        if (!$this->file->getSize()) {
89
            return null;
90
        }
91
92
        $this->file->rewind();
93
94
        $contents = $this->file->fread($this->file->getSize());
95
96
        return unserialize($contents);
97
    }
98
99
    /**
100
     * @param Robot $robot
101
     */
102 1
    public function saveRobot(Robot $robot): void
103
    {
104
        // Empty the file
105 1
        $this->file->ftruncate(0);
106
107 1
        $this->file->rewind();
108
109
        // Save the robot
110 1
        $bytes = $this->file->fwrite(serialize($robot));
111 1
        $this->file->fflush();
112
113 1
        $this->log(sprintf('Wrote [%d] robot bytes to [%s]', $bytes, $this->file->getRealPath()));
114 1
    }
115
116
    /**
117
     * @param string $msg
118
     */
119 1
    private function log(string $msg): void
120
    {
121 1
        if (!$this->logger) {
122 1
            return;
123
        }
124
125
        $this->logger->info($msg);
126
    }
127
}
128