findByPackageName()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.4285
cc 3
eloc 6
nc 3
nop 1
crap 3
1
<?php
2
3
namespace MagentoHackathon\Composer\Magento\Repository;
4
5
use MagentoHackathon\Composer\Magento\InstalledPackage;
6
use MagentoHackathon\Composer\Magento\InstalledPackageDumper;
7
8
/**
9
 * Class InstalledPackageFileSystemRepository
10
 * @package MagentoHackathon\Composer\Magento\Repository
11
 * @author Aydin Hassan <[email protected]>
12
 */
13
class InstalledPackageFileSystemRepository implements InstalledPackageRepositoryInterface
14
{
15
16
    /**
17
     * @var string Path to state file
18
     */
19
    protected $filePath;
20
21
    /**
22
     * @var array
23
     */
24
    protected $packages = array();
25
26
    /**
27
     * @var bool Flag to indicate if we have read the existing file
28
     */
29
    protected $isLoaded = false;
30
31
    /**
32
     * @var bool Flag to indicate if we need to write once we are finished
33
     */
34
    protected $hasChanges = false;
35
36
    /**
37
     * @var InstalledPackageDumper
38
     */
39
    protected $dumper;
40
41
    /**
42
     * If file exists, check its readable
43
     * Check in any case that it's writeable
44
     *
45
     * @param string $filePath
46
     * @param InstalledPackageDumper $dumper
47
     */
48 18
    public function __construct($filePath, InstalledPackageDumper $dumper)
49
    {
50 18 View Code Duplication
        if (file_exists($filePath) && !is_writable($filePath)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
51 1
            throw new \InvalidArgumentException(sprintf('File "%s" is not writable', $filePath));
52
        }
53
54 18
        if (file_exists($filePath) && !is_readable($filePath)) {
55 1
            throw new \InvalidArgumentException(sprintf('File "%s" is not readable', $filePath));
56
        }
57
58 18 View Code Duplication
        if (!file_exists($filePath) && !is_writable(dirname($filePath))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
59 1
            throw new \InvalidArgumentException(sprintf('Directory "%s" is not writable', dirname($filePath)));
60
        }
61
62 18
        $this->filePath = $filePath;
63 18
        $this->dumper = $dumper;
64 18
    }
65
66
    /**
67
     * @return array
68
     */
69 8
    public function findAll()
70
    {
71 8
        $this->load();
72 8
        return $this->packages;
73
    }
74
75
    /**
76
     * @param string $packageName
77
     * @return InstalledPackage
78
     * @throws \Exception
79
     */
80 13
    public function findByPackageName($packageName)
81
    {
82 13
        $this->load();
83 13
        foreach ($this->packages as $package) {
84 8
            if ($package->getName() === $packageName) {
85 8
                return $package;
86
            }
87
        }
88
89 12
        throw new \Exception(sprintf('Package Installed Files for: "%s" not found', $packageName));
90
    }
91
92
    /**
93
     * If version specified, perform a strict check,
94
     * which only returns true if repository has the package in the specified version
95
     *
96
     * @param string $packageName
97
     * @param string $version
98
     * @return bool
99
     */
100 6
    public function has($packageName, $version = null)
101
    {
102 6
        $this->load();
103
        try {
104 6
            $package = $this->findByPackageName($packageName);
105
106 5
            if (null === $version) {
107
                return true;
108
            }
109
110 5
            return $package->getVersion() === $version;
111 3
        } catch (\Exception $e) {
112 3
            return false;
113
        }
114
    }
115
116
    /**
117
     * @param InstalledPackage $package
118
     * @throws \Exception
119
     */
120 11
    public function add(InstalledPackage $package)
121
    {
122 11
        $this->load();
123
124
        try {
125 11
            $this->findByPackageName($package->getName());
126 11
        } catch (\Exception $e) {
127 11
            $this->packages[] = $package;
128 11
            $this->hasChanges = true;
129 11
            return;
130
        }
131
132 1
        throw new \Exception(sprintf('Package: "%s" is already installed', $package->getName()));
133
    }
134
135
    /**
136
     * @param InstalledPackage $package
137
     * @throws \Exception
138
     */
139 7
    public function remove(InstalledPackage $package)
140
    {
141 7
        $this->load();
142
143 7
        foreach ($this->packages as $key => $installedPackage) {
144 6
            if ($installedPackage->getName() === $package->getName()) {
145 6
                array_splice($this->packages, $key, 1);
146 6
                $this->hasChanges = true;
147 6
                return;
148
            }
149
        }
150
151 1
        throw new \Exception(sprintf('Package: "%s" not found', $package->getName()));
152
    }
153
154
    /**
155
     * Load the Mappings File
156
     *
157
     * @return array
158
     */
159 14
    private function load()
160
    {
161 14
        if (!$this->isLoaded && file_exists($this->filePath)) {
162 1
            $data = json_decode(file_get_contents($this->filePath), true);
163
164 1
            foreach ($data as $installedPackageData) {
165 1
                $this->packages[] = $this->dumper->restore($installedPackageData);
166
            }
167
        }
168
169 14
        $this->isLoaded = true;
170 14
    }
171
172
    /**
173
     * Do the write on destruct, we shouldn't have to do this manually
174
     * - you don't call save after adding an entry to the database
175
     * and at the same time, do want to perform IO for each package addition/removal.
176
     *
177
     * Also I don't like enforcing the consumer to call save and load.
178
     */
179 11
    public function __destruct()
180
    {
181 11
        if ($this->hasChanges) {
182 4
            $data = array();
183 4
            foreach ($this->packages as $installedPackage) {
184 3
                $data[] = $this->dumper->dump($installedPackage);
185
            }
186
187 4
            file_put_contents($this->filePath, json_encode($data, JSON_PRETTY_PRINT));
188
        }
189 11
    }
190
}
191