GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 89babd...5ed7d9 )
by
unknown
79:45 queued 23:58
created

Git_Mirror_MirrorDataMapper   F

Complexity

Total Complexity 63

Size/Duplication

Total Lines 381
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 18
Metric Value
wmc 63
lcom 2
cbo 18
dl 0
loc 381
rs 2.9203

30 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
B save() 0 21 5
A checkThatHostnameIsValidOnCreation() 0 15 4
A doesHostnameIsForbidden() 0 4 2
A checkThatHostnameIsValidOnUpdate() 0 15 4
A createUserForMirror() 0 12 1
A fetchAll() 0 5 1
A fetchAllForProject() 0 5 1
A fetchAllRepositoryMirrors() 0 9 2
A mapDataAccessResultToArrayOfMirrors() 0 9 2
A fetchRepositoriesForMirror() 0 8 2
A fetchAllProjectRepositoriesForMirror() 0 10 2
A fetchRepositoriesPerMirrorPresenters() 0 20 3
A fetchAllProjectsConcernedByMirroring() 0 9 2
A fetchAllProjectsConcernedByAMirror() 0 9 2
A doesAllSelectedMirrorIdsExist() 0 6 2
A unmirrorRepository() 0 3 1
A mirrorRepositoryTo() 0 6 2
A removeAllDefaultMirrorsToProject() 0 3 1
A addDefaultMirrorsToProject() 0 7 2
A getDefaultMirrorIdsForProject() 0 3 1
B update() 0 21 8
A delete() 0 14 2
A deleteFromDefaultMirrors() 0 3 1
A deleteFromDefaultMirrorsInProjects() 0 3 1
A fetch() 0 9 2
A getListOfMirrorIdsPerRepositoryForProject() 0 12 3
A getInstanceFromRow() 0 9 1
A getMirrorOwner() 0 5 1
A duplicate() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Git_Mirror_MirrorDataMapper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Git_Mirror_MirrorDataMapper, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Copyright (c) Enalean, 2014-2016. All rights reserved
4
 *
5
 * This file is a part of Tuleap.
6
 *
7
 * Tuleap is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * Tuleap is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with Tuleap. If not, see <http://www.gnu.org/licenses/
19
 */
20
21
class Git_Mirror_MirrorDataMapper {
22
23
    const MIRROR_OWNER_PREFIX = 'forge__gitmirror_';
24
    const PROJECTS_HOSTNAME   = 'projects';
25
26
    /** @var Git_Mirror_MirrorDao */
27
    private $dao;
28
29
    /** UserManager */
30
    private $user_manager;
31
32
    /**
33
     * @var GitRepositoryFactory
34
     */
35
    private $repository_factory;
36
37
    /** @var ProjectManager */
38
    private $project_manager;
39
40
    /** @var Git_SystemEventManager */
41
    private $git_system_event_manager;
42
43
    /** @var Git_Gitolite_GitoliteRCReader */
44
    private $reader;
45
46
    /**
47
     * @var DefaultProjectMirrorDao
48
     */
49
    private $default_dao;
50
51
    public function __construct(
52
        Git_Mirror_MirrorDao $dao,
53
        UserManager $user_manager,
54
        GitRepositoryFactory $repository_factory,
55
        ProjectManager $project_manager,
56
        Git_SystemEventManager $git_system_event_manager,
57
        Git_Gitolite_GitoliteRCReader $reader,
58
        DefaultProjectMirrorDao $default_dao
59
    ) {
60
        $this->dao                      = $dao;
61
        $this->user_manager             = $user_manager;
62
        $this->repository_factory       = $repository_factory;
63
        $this->project_manager          = $project_manager;
64
        $this->git_system_event_manager = $git_system_event_manager;
65
        $this->reader                   = $reader;
66
        $this->default_dao              = $default_dao;
67
    }
68
69
    /**
70
     * @return Git_Mirror_Mirror
71
     * @throws Git_Mirror_MissingDataException
72
     * @throws Git_Mirror_CreateException
73
     */
74
    public function save($url, $hostname, $ssh_key, $password, $name) {
75
        if (! $url || ! $ssh_key || ! $name) {
76
            throw new Git_Mirror_MissingDataException();
77
        }
78
79
        $this->checkThatHostnameIsValidOnCreation($hostname);
80
81
        $mirror_id = $this->dao->save($url, $hostname, $name);
82
        if (! $mirror_id) {
83
            throw new Git_Mirror_CreateException();
84
        }
85
86
        $user = $this->createUserForMirror($mirror_id, $password, $ssh_key);
87
88
        return $this->getInstanceFromRow($user, array(
89
            'id'       => $mirror_id,
90
            'url'      => $url,
91
            'hostname' => $hostname,
92
            'name'     => $name
93
        ));
94
    }
95
96
    private function checkThatHostnameIsValidOnCreation($hostname) {
97
        if (! $hostname) {
98
            return true;
99
        }
100
101
        if ($this->dao->getNumberOfMirrorByHostname($hostname) > 0) {
102
            throw new Git_Mirror_HostnameAlreadyUsedException();
103
        }
104
105
        if ($this->doesHostnameIsForbidden($hostname)) {
106
            throw new Git_Mirror_HostnameIsReservedException();
107
        }
108
109
        return true;
110
    }
111
112
    private function doesHostnameIsForbidden($hostname) {
113
        return strtolower($hostname) === self::PROJECTS_HOSTNAME ||
114
               strtolower($hostname) === strtolower($this->reader->getHostname());
115
    }
116
117
    private function checkThatHostnameIsValidOnUpdate($id, $hostname) {
118
        if (! $hostname) {
119
            return true;
120
        }
121
122
        if ($this->dao->getNumberOfMirrorByHostnameExcludingGivenId($hostname, $id) > 0) {
123
            throw new Git_Mirror_HostnameAlreadyUsedException();
124
        }
125
126
        if ($this->doesHostnameIsForbidden($hostname)) {
127
            throw new Git_Mirror_HostnameIsReservedException();
128
        }
129
130
        return true;
131
    }
132
133
    private function createUserForMirror($mirror_id, $password, $ssh_key) {
134
        $user = new PFUser(array(
135
            'user_name'       => self::MIRROR_OWNER_PREFIX.$mirror_id,
136
            'status'          => 'A',
137
            'unix_status'     => 'A'
138
        ));
139
        $user->setPassword($password);
140
        $this->user_manager->createAccount($user);
141
        $this->user_manager->addSSHKeys($user, $ssh_key);
142
143
        return $user;
144
    }
145
146
    /**
147
     * @return Git_Mirror_Mirror[]
148
     */
149
    public function fetchAll() {
150
        $rows = $this->dao->fetchAll();
151
152
        return $this->mapDataAccessResultToArrayOfMirrors($rows);
153
    }
154
155
    /**
156
     * @return Git_Mirror_Mirror[]
157
     */
158
    public function fetchAllForProject(Project $project) {
159
        $rows = $this->dao->fetchAllForProject($project->getID());
160
161
        return $this->mapDataAccessResultToArrayOfMirrors($rows);
162
    }
163
164
    /**
165
     * @return Git_Mirror_Mirror[]
166
     */
167
    public function fetchAllRepositoryMirrors(GitRepository $repository) {
168
        if ($repository instanceof GitRepositoryGitoliteAdmin) {
169
            return $this->fetchAll();
170
        }
171
172
        $rows = $this->dao->fetchAllRepositoryMirrors($repository->getId());
173
174
        return $this->mapDataAccessResultToArrayOfMirrors($rows);
175
    }
176
177
    /**
178
     * @return Git_Mirror_Mirror[]
179
     */
180
    private function mapDataAccessResultToArrayOfMirrors(DataAccessResult $rows) {
181
        $mirrors = array();
182
        foreach ($rows as $row) {
183
            $owner     = $this->getMirrorOwner($row['id']);
184
            $mirrors[] = $this->getInstanceFromRow($owner, $row);
185
        }
186
187
        return $mirrors;
188
    }
189
190
    public function fetchRepositoriesForMirror(Git_Mirror_Mirror $mirror) {
191
        $repositories = array();
192
        foreach ($this->dao->fetchAllRepositoryMirroredByMirror($mirror->id) as $row) {
0 ignored issues
show
Bug introduced by
The expression $this->dao->fetchAllRepo...edByMirror($mirror->id) of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
193
            $repositories[] = $this->repository_factory->instanciateFromRow($row);
194
        }
195
196
        return $repositories;
197
    }
198
199
    public function fetchAllProjectRepositoriesForMirror(Git_Mirror_Mirror $mirror, array $project_ids) {
200
        $rows         = $this->dao->fetchAllProjectRepositoriesForMirror($mirror->id, $project_ids);
201
        $repositories = array();
202
203
        foreach ($rows as $row) {
0 ignored issues
show
Bug introduced by
The expression $rows of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
204
            $repositories[] = $this->repository_factory->instanciateFromRow($row);
205
        }
206
207
        return $repositories;
208
    }
209
210
    public function fetchRepositoriesPerMirrorPresenters(Git_Mirror_Mirror $mirror) {
211
        $presenters = array();
212
213
        $previous_group_id = -1;
214
        foreach ($this->dao->fetchAllRepositoryMirroredByMirror($mirror->id) as $row) {
0 ignored issues
show
Bug introduced by
The expression $this->dao->fetchAllRepo...edByMirror($mirror->id) of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
215
            if ($previous_group_id !== $row['group_id']) {
216
                $project_presenter = new Git_AdminRepositoryListForProjectPresenter($row['group_id'], $row['group_name']);
217
                $presenters[]      = $project_presenter;
218
            }
219
220
            $project_presenter->repositories[] = array(
221
                'repository_id'   => $row['repository_id'],
222
                'repository_path' => $row['repository_path'],
223
            );
224
225
            $previous_group_id = $row['group_id'];
226
        }
227
228
        return $presenters;
229
    }
230
231
    /**
232
     * @return Project[]
233
     */
234
    public function fetchAllProjectsConcernedByMirroring() {
235
        $projects = array();
236
237
        foreach ($this->dao->fetchAllProjectIdsConcernedByMirroring() as $row) {
0 ignored issues
show
Bug introduced by
The expression $this->dao->fetchAllProj...sConcernedByMirroring() of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
238
            $projects[] = $this->project_manager->getProject($row['project_id']);
239
        }
240
241
        return $projects;
242
    }
243
244
    public function fetchAllProjectsConcernedByAMirror(Git_Mirror_Mirror $mirror) {
245
        $projects = array();
246
247
        foreach ($this->dao->fetchAllProjectIdsConcernedByAMirror($mirror->id) as $row) {
0 ignored issues
show
Bug introduced by
The expression $this->dao->fetchAllProj...dByAMirror($mirror->id) of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
248
            $projects[] = $this->project_manager->getProject($row['project_id']);
249
        }
250
251
        return $projects;
252
    }
253
254
    public function doesAllSelectedMirrorIdsExist($selected_mirror_ids) {
255
        if ($selected_mirror_ids) {
256
            return count($selected_mirror_ids) === count($this->dao->fetchByIds($selected_mirror_ids));
257
        }
258
        return true;
259
    }
260
261
    public function unmirrorRepository($repository_id) {
262
        return $this->dao->unmirrorRepository($repository_id);
263
    }
264
265
    public function mirrorRepositoryTo($repository_id, $selected_mirror_ids) {
266
        if ($selected_mirror_ids) {
267
            return $this->dao->mirrorRepositoryTo($repository_id, $selected_mirror_ids);
268
        }
269
        return true;
270
    }
271
272
    public function removeAllDefaultMirrorsToProject(Project $project) {
273
        return $this->default_dao->removeAllToProject($project->getID());
274
    }
275
276
    public function addDefaultMirrorsToProject(Project $project, array $selected_mirror_ids) {
277
        if ($selected_mirror_ids) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $selected_mirror_ids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
278
            return $this->default_dao->addDefaultMirrorsToProject($project->getID(), $selected_mirror_ids);
279
        }
280
281
        return true;
282
    }
283
284
    public function getDefaultMirrorIdsForProject(Project $project) {
285
        return $this->default_dao->getDefaultMirrorIdsForProject($project->getID());
286
    }
287
288
    /**
289
     * @return bool
290
     * @throws Git_Mirror_MirrorNoChangesException
291
     * @throws Git_Mirror_MirrorNotFoundException
292
     * @throws Git_Mirror_MissingDataException
293
     */
294
    public function update($id, $url, $hostname, $ssh_key, $name) {
295
        $mirror = $this->fetch($id);
296
297
        if ($url == $mirror->url && $hostname == $mirror->hostname && $ssh_key == $mirror->ssh_key && $name == $mirror->name) {
298
            throw new Git_Mirror_MirrorNoChangesException();
299
        }
300
301
        $this->checkThatHostnameIsValidOnUpdate($id, $hostname);
302
303
        if (! $url || ! $ssh_key) {
304
            throw new Git_Mirror_MissingDataException();
305
        }
306
307
        if ($ssh_key != $mirror->ssh_key) {
308
            $this->user_manager->updateUserSSHKeys($mirror->owner, array($ssh_key));
309
        }
310
311
        $this->git_system_event_manager->queueUpdateMirror($id, $mirror->hostname);
312
313
        return $this->dao->updateMirror($id, $url, $hostname, $name);
314
    }
315
316
    /**
317
     * @return bool
318
     * @throws Git_Mirror_MirrorNotFoundException
319
     */
320
    public function delete($id) {
321
        $mirror = $this->fetch($id);
322
323
        if (! $this->dao->delete($id)) {
324
            return false;
325
        }
326
327
        $user = $this->user_manager->getUserById($mirror->owner_id);
328
        $user->setStatus(PFUser::STATUS_DELETED);
329
        $this->user_manager->updateDb($user);
330
        $this->git_system_event_manager->queueDeleteMirror($id, $mirror->hostname);
331
332
        return true;
333
    }
334
335
    /**
336
     * @return bool
337
     */
338
    public function deleteFromDefaultMirrors($deleted_mirror_id) {
339
        return $this->default_dao->deleteFromDefaultMirrors($deleted_mirror_id);
340
    }
341
342
    public function deleteFromDefaultMirrorsInProjects(Git_Mirror_Mirror $mirror, array $project_ids) {
343
        return $this->default_dao->deleteFromDefaultMirrorsInProjects($mirror->id, $project_ids);
344
    }
345
346
    /**
347
     * @return Git_Mirror_Mirror
348
     * @throws Git_Mirror_MirrorNotFoundException
349
     */
350
    public function fetch($id) {
351
        $row = $this->dao->fetch($id);
352
        if (! $row) {
353
            throw new Git_Mirror_MirrorNotFoundException();
354
        }
355
        $owner = $this->getMirrorOwner($row['id']);
356
357
        return $this->getInstanceFromRow($owner, $row);
358
    }
359
360
    public function getListOfMirrorIdsPerRepositoryForProject(Project $project) {
361
        $repositories = array();
362
        foreach ($this->dao->fetchAllRepositoryMirroredInProject($project->getId()) as $row) {
0 ignored issues
show
Bug introduced by
The expression $this->dao->fetchAllRepo...ject($project->getId()) of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
363
            if (! isset($repositories[$row['repository_id']])) {
364
                $repositories[$row['repository_id']] = array();
365
            }
366
367
            $repositories[$row['repository_id']][] = $row['mirror_id'];
368
        }
369
370
        return $repositories;
371
    }
372
373
    /**
374
     * @return Git_Mirror_Mirror
375
     */
376
    private function getInstanceFromRow(PFUser $owner, $row) {
377
        return new Git_Mirror_Mirror(
378
            $owner,
379
            $row['id'],
380
            $row['url'],
381
            $row['hostname'],
382
            $row['name']
383
        );
384
    }
385
386
    /**
387
     * @return PFUser
388
     */
389
    private function getMirrorOwner($mirror_id) {
390
        return $this->user_manager->getUserByUserName(
391
            self::MIRROR_OWNER_PREFIX.$mirror_id
392
        );
393
    }
394
395
    /**
396
     * @return boolean
397
     */
398
    public function duplicate($template_project_id, $new_project_id) {
399
        return $this->default_dao->duplicate($template_project_id, $new_project_id);
400
    }
401
}
402