HumbugAdapter::getOldVersion()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Sugarcrm\UpgradeSpec\Updater\Adapter;
4
5
use Humbug\SelfUpdate\Strategy\GithubStrategy;
6
use Humbug\SelfUpdate\Updater as HumbugUpdater;
7
use Sugarcrm\UpgradeSpec\Updater\Updater;
8
9
class HumbugAdapter implements AdapterInterface
10
{
11
    /**
12
     * @var HumbugUpdater
13
     */
14
    private $updater;
15
16
    /**
17
     * HumbugAdapter constructor.
18
     *
19
     * @param HumbugUpdater $updater
20
     */
21
    public function __construct(HumbugUpdater $updater)
22
    {
23
        $this->updater = $updater;
24
    }
25
26
    /**
27
     * @return bool
28
     */
29
    public function hasUpdate()
30
    {
31
        return $this->updater->hasUpdate();
32
    }
33
34
    /**
35
     * @return mixed
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
36
     */
37
    public function getOldVersion()
38
    {
39
        return $this->updater->getOldVersion();
40
    }
41
42
    /**
43
     * @return mixed
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
44
     */
45
    public function getNewVersion()
46
    {
47
        return $this->updater->getNewVersion();
48
    }
49
50
    /**
51
     * @param string $stability
52
     *
53
     * @return bool
54
     */
55
    public function update($stability = Updater::STABILITY_ANY)
56
    {
57
        $strategy = $this->updater->getStrategy();
58
        if ($strategy instanceof GithubStrategy) {
59
            $this->updater->getStrategy()->setStability($this->getGithubStability($stability));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Humbug\SelfUpdate\Strategy\StrategyInterface as the method setStability() does only exist in the following implementations of said interface: Humbug\SelfUpdate\Strategy\GithubStrategy, Humbug\Test\SelfUpdate\GithubTestStrategy.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
60
        }
61
62
        $result = $this->updater->update();
63
64
        $this->performCleanup();
65
66
        return $result;
67
    }
68
69
    /**
70
     * @return bool
71
     */
72
    public function rollback()
73
    {
74
        return $this->updater->rollback();
75
    }
76
77
    /**
78
     * @param $stability
79
     *
80
     * @return string
81
     */
82
    private function getGithubStability($stability)
83
    {
84
        if ($stability == Updater::STABILITY_STABLE) {
85
            return GithubStrategy::STABLE;
86
        }
87
88
        if ($stability == Updater::STABILITY_UNSTABLE) {
89
            return GithubStrategy::UNSTABLE;
90
        }
91
92
        return GithubStrategy::ANY;
93
    }
94
95
    /**
96
     * Removes PHAR update leftovers.
97
     */
98
    private function performCleanup()
99
    {
100
        $directory = $this->updater->getTempDirectory();
101
        $fileBasename = $this->updater->getLocalPharFileBasename();
102
103
        @unlink(sprintf('%s/%s.phar.temp.pubkey', $directory, $fileBasename));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
104
        @unlink(sprintf('%s/%s.temp.pubkey', $directory, $fileBasename));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
105
    }
106
}
107