AddonUpdater::updateLinks()   B
last analyzed

Complexity

Conditions 7
Paths 5

Size

Total Lines 54
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 54
rs 7.8331
c 0
b 0
f 0
cc 7
eloc 26
nc 5
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
use Composer\Package\AliasPackage;
4
use Composer\Package\CompletePackage;
5
use Guzzle\Http\Exception\ClientErrorResponseException;
6
use SilverStripe\Elastica\ElasticaService;
7
use Packagist\Api\Result\Package;
8
use Composer\Package\Version\VersionParser;
9
use Packagist\Api\Result\Package\Version;
10
11
/**
12
 * Updates all add-ons from Packagist.
13
 */
14
class AddonUpdater
15
{
16
17
    /**
18
     * @var PackagistService
19
     */
20
    private $packagist;
21
22
    /**
23
     * @var SilverStripe\Elastica\ElasticaService
24
     */
25
    private $elastica;
26
27
    /**
28
     * @var SilverStripeVersion[]
29
     */
30
    private $silverstripes;
31
32
    public function __construct(
33
        PackagistService $packagist,
34
        ElasticaService $elastica
35
    ) {
36
        $this->packagist = $packagist;
37
        $this->elastica = $elastica;
38
39
        $this->setSilverStripeVersions(SilverStripeVersion::get());
40
    }
41
42
    /**
43
     * Updates all add-ons.
44
     *
45
     * @param Boolean Clear existing addons before updating them.
46
     * Will also clear their search index, and cascade the delete for associated data.
47
     * @param Array Limit to specific addons, using their name incl. vendor prefix.
48
     */
49
    public function update($clear = false, $limitAddons = null)
50
    {
51
        if ($clear && !$limitAddons) {
52
            Addon::get()->removeAll();
53
            AddonAuthor::get()->removeAll();
54
            AddonKeyword::get()->removeAll();
55
            AddonLink::get()->removeAll();
56
            AddonVendor::get()->removeAll();
57
            AddonVersion::get()->removeAll();
58
        }
59
60
        // This call to packagist can be expensive. Requests are served from a cache if usePackagistCache() returns true
61
        $cache = SS_Cache::factory('addons');
62
63
        if ($this->usePackagistCache() && $packages = $cache->load('packagist')) {
64
            $packages = unserialize($packages);
65
        } else {
66
            $packages = $this->packagist->getPackages();
67
            $cache->save(serialize($packages), 'packagist');
68
        }
69
70
        // TODO: AWS elasticsearch doesn't have this setting enabled
71
        // https://www.elastic.co/guide/en/elasticsearch/reference/5.2/url-access-control.html
72
        // and bulk index operations by elastica currently require it
73
        // Switching to https://github.com/heyday/silverstripe-elastica and SS4 might help
74
75
        // $this->elastica->startBulkIndex();
76
77
        foreach ($packages as $package) {
78
            /** @var Packagist\Api\Result\Package $package */
79
80
            $isAbandoned = (method_exists($package, 'isAbandoned') && $package->isAbandoned());
81
            $name = $package->getName();
82
            $versions = $package->getVersions();
83
84
            if ($limitAddons && !in_array($name, $limitAddons)) {
85
                continue;
86
            }
87
88
            $addon = Addon::get()->filter('Name', $name)->first();
89
90
            if (!$addon) {
91
                if ($isAbandoned) {
92
                    echo ' - Skipping abandoned package: ' . $name, PHP_EOL;
93
                    continue;
94
                }
95
96
                $addon = new Addon();
97
                $addon->Name = $name;
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
98
                $addon->write();
99
            }
100
101
            if ($isAbandoned) {
102
                echo ' - Removing abandoned package: ' . $name, PHP_EOL;
103
                $addon->delete();
104
                continue;
105
            }
106
107
            usort($versions, function ($a, $b) {
108
                return version_compare($a->getVersionNormalized(), $b->getVersionNormalized());
109
            });
110
111
            $this->updateAddon($addon, $package, $versions);
0 ignored issues
show
Compatibility introduced by
$addon of type object<DataObject> is not a sub-type of object<Addon>. It seems like you assume a child class of the class DataObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
112
        }
113
114
        // $this->elastica->endBulkIndex();
115
    }
116
117
118
119
    /**
120
     * Check whether or not we should contact packagist or use a cached version. This allows to speed up the task
121
     * during development.
122
     *
123
     * @return bool
124
     */
125
    protected function usePackagistCache()
126
    {
127
        return Director::isDev();
128
    }
129
130
    private function updateAddon(Addon $addon, Package $package, array $versions)
131
    {
132
        echo "Updating addon {$addon->Name}:\n";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<Addon>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
133
134
        if (!$addon->VendorID) {
0 ignored issues
show
Documentation introduced by
The property VendorID does not exist on object<Addon>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
135
            $vendor = AddonVendor::get()->filter('Name', $addon->VendorName())->first();
136
137
            if (!$vendor) {
138
                $vendor = new AddonVendor();
139
                $vendor->Name = $addon->VendorName();
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<AddonVendor>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
140
                $vendor->write();
141
            }
142
143
            echo " - Set vendor name to {$vendor->Name}\n";
144
145
            $addon->VendorID = $vendor->ID;
0 ignored issues
show
Documentation introduced by
The property VendorID does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
146
        }
147
148
        $addon->Type = preg_replace('/^silverstripe-(vendor)?/', '', $package->getType());
0 ignored issues
show
Documentation introduced by
The property Type does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
149
        $addon->Description = $package->getDescription();
0 ignored issues
show
Documentation introduced by
The property Description does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
150
        $addon->Released = strtotime($package->getTime());
0 ignored issues
show
Documentation introduced by
The property Released does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
151
        $addon->Repository = $package->getRepository();
0 ignored issues
show
Documentation introduced by
The property Repository does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
152
        $addon->Downloads = $package->getDownloads()->getTotal();
0 ignored issues
show
Documentation introduced by
The property Downloads does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
153
        $addon->DownloadsMonthly = $package->getDownloads()->getMonthly();
0 ignored issues
show
Documentation introduced by
The property DownloadsMonthly does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
154
        $addon->Favers = $package->getFavers();
0 ignored issues
show
Documentation introduced by
The property Favers does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
155
156
        foreach ($versions as $version) {
157
            $this->updateVersion($addon, $version);
158
        }
159
160
        // If there is no build, then queue one up if the add-on requires
161
        // one.
162
        if (!$addon->BuildQueued) {
0 ignored issues
show
Documentation introduced by
The property BuildQueued does not exist on object<Addon>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
163
            echo " - Will queue a rebuild\n";
164
            if (!$addon->BuiltAt) {
0 ignored issues
show
Documentation introduced by
The property BuiltAt does not exist on object<Addon>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
165
                $buildJob = new BuildAddonJob(['package' => $addon->ID]);
166
                singleton('QueuedJobService')->queueJob($buildJob);
167
                echo " - Queued {$addon->Name} for build\n";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<Addon>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
168
                $addon->BuildQueued = true;
0 ignored issues
show
Documentation introduced by
The property BuildQueued does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
169
            } else {
170
                $built = (int) $addon->obj('BuiltAt')->format('U');
171
172
                foreach ($versions as $version) {
173
                    if (strtotime($version->getTime()) > $built) {
174
                        $buildJob = new BuildAddonJob(['package' => $addon->ID]);
175
                        singleton('QueuedJobService')->queueJob($buildJob);
176
                        echo " - Queued {$addon->Name} version {$version->Name} for build\n";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<Addon>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
177
                        $addon->BuildQueued = true;
0 ignored issues
show
Documentation introduced by
The property BuildQueued does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
178
179
                        break;
180
                    }
181
                }
182
            }
183
        } else {
184
            echo " - Will not queue a rebuild\n";
185
        }
186
187
        $addon->LastUpdated = time();
0 ignored issues
show
Documentation introduced by
The property LastUpdated does not exist on object<Addon>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
188
        $addon->write();
189
    }
190
191
    private function updateVersion(Addon $addon, Version $package)
192
    {
193
        $version = null;
194
195
        if ($addon->isInDB()) {
196
            $version = $addon->Versions()->filter('Version', $package->getVersionNormalized())->first();
0 ignored issues
show
Bug introduced by
The method Versions() does not exist on Addon. Did you maybe mean SortedVersions()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
197
        }
198
199
        if (!$version) {
200
            $version = new AddonVersion();
201
        }
202
203
        $version->Name = $package->getName();
204
        $version->Type = preg_replace('/^silverstripe-(vendor)?/', '', $package->getType());
205
        $version->Description = $package->getDescription();
206
        $version->Released = strtotime($package->getTime());
207
        $keywords = $package->getKeywords();
208
209
        if ($keywords) {
210
            foreach ($keywords as $keyword) {
0 ignored issues
show
Bug introduced by
The expression $keywords of type string is not traversable.
Loading history...
211
                $keyword = AddonKeyword::get_by_name($keyword);
212
213
                $addon->Keywords()->add($keyword);
0 ignored issues
show
Documentation Bug introduced by
The method Keywords does not exist on object<Addon>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
214
                $version->Keywords()->add($keyword);
215
            }
216
        }
217
218
        $version->Version = $package->getVersionNormalized();
219
        $version->PrettyVersion = $package->getVersion();
220
221
        $stability = VersionParser::parseStability($package->getVersion());
222
        $isDev = $stability === 'dev';
223
        $version->Development = $isDev;
224
225
        $version->SourceType = $package->getSource()->getType();
226
        $version->SourceUrl = $package->getSource()->getUrl();
227
        $version->SourceReference = $package->getSource()->getReference();
228
229
        if ($package->getDist()) {
230
            $version->DistType = $package->getDist()->getType();
231
            $version->DistUrl = $package->getDist()->getUrl();
232
            $version->DistReference = $package->getDist()->getReference();
233
            $version->DistChecksum = $package->getDist()->getShasum();
234
        }
235
236
        $version->Extra = $package->getExtra();
237
        $version->Homepage = $package->getHomepage();
238
        $version->License = $package->getLicense();
239
        // $version->Support = $package->getSupport();
240
241
        echo " - Processed version {$version->Version}\n";
242
243
        $addon->Versions()->add($version);
0 ignored issues
show
Bug introduced by
The method Versions() does not exist on Addon. Did you maybe mean SortedVersions()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
244
245
        $this->updateLinks($version, $package);
246
        $this->updateCompatibility($addon, $version, $package);
247
        $this->updateAuthors($version, $package);
248
    }
249
250
    private function updateLinks(AddonVersion $version, Version $package)
251
    {
252
        $getLink = function ($name, $type) use ($version) {
253
            $link = null;
254
255
            if ($version->isInDB()) {
256
                $link = $version->Links()->filter('Name', $name)->filter('Type', $type)->first();
0 ignored issues
show
Documentation Bug introduced by
The method Links does not exist on object<AddonVersion>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
257
            }
258
259
            if (!$link) {
260
                $link = new AddonLink();
261
                $link->Name = $name;
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<AddonLink>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
262
                $link->Type = $type;
0 ignored issues
show
Documentation introduced by
The property Type does not exist on object<AddonLink>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
263
            }
264
265
            return $link;
266
        };
267
268
        $types = array(
269
            'require' => 'getRequire',
270
            'require-dev' => 'getRequireDev',
271
            'provide' => 'getProvide',
272
            'conflict' => 'getConflict',
273
            'replace' => 'getReplace'
274
        );
275
276
        foreach ($types as $type => $method) {
277
            if ($linked = $package->$method()) {
278
                foreach ($linked as $link => $constraint) {
279
                    $name = $link;
280
                    $addon = Addon::get()->filter('Name', $name)->first();
281
282
                    $local = $getLink($name, $type);
283
                    $local->Constraint = $constraint;
284
285
                    if ($addon) {
286
                        $local->TargetID = $addon->ID;
287
                    }
288
289
                    $version->Links()->add($local);
0 ignored issues
show
Documentation Bug introduced by
The method Links does not exist on object<AddonVersion>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
290
                }
291
            }
292
        }
293
294
        //to-do api have no method to get this.
295
        /*$suggested = $package->getSuggests();
296
297
		if ($suggested) foreach ($suggested as $package => $description) {
298
			$link = $getLink($package, 'suggest');
299
			$link->Description = $description;
300
301
			$version->Links()->add($link);
302
		}*/
303
    }
304
305
    private function updateCompatibility(Addon $addon, AddonVersion $version, Version $package)
306
    {
307
        $require = null;
308
309
        if ($package->getRequire()) {
310
            foreach ($package->getRequire() as $name => $link) {
311
                if ((string)$link == 'self.version') {
312
                    continue;
313
                }
314
315
                if ($name == 'silverstripe/framework') {
316
                    $require = $link;
317
                    break;
318
                }
319
320
                if ($name == 'silverstripe/cms') {
321
                    $require = $link;
322
                }
323
            }
324
        }
325
326
        if (!$require) {
327
            return;
328
        }
329
330
        //  >= interpreted as ^, see https://github.com/silverstripe/addons.silverstripe.org/issues/160
331
        $require = preg_replace('/^>=/', '^', $require);
332
333
        $addon->CompatibleVersions()->removeAll();
0 ignored issues
show
Documentation Bug introduced by
The method CompatibleVersions does not exist on object<Addon>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
334
        $version->CompatibleVersions()->removeAll();
0 ignored issues
show
Documentation Bug introduced by
The method CompatibleVersions does not exist on object<AddonVersion>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
335
336
        foreach ($this->getSilverStripeVersions() as $silverStripeVersion) {
337
            /** @var SilverStripeVersion $silverStripeVersion */
338
            try {
339
                if ($silverStripeVersion->getConstraintValidity($require)) {
340
                    $addon->CompatibleVersions()->add($silverStripeVersion);
0 ignored issues
show
Documentation Bug introduced by
The method CompatibleVersions does not exist on object<Addon>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
341
                    $version->CompatibleVersions()->add($silverStripeVersion);
0 ignored issues
show
Documentation Bug introduced by
The method CompatibleVersions does not exist on object<AddonVersion>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
342
                }
343
            } catch (Exception $e) {
344
                // An exception here shouldn't prevent further updates.
345
                Debug::log($addon->Name . "\t" . $addon->ID . "\t" . $e->getMessage());
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<Addon>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
346
            }
347
        }
348
    }
349
350
    private function updateAuthors(AddonVersion $version, Version $package)
351
    {
352
        if ($package->getAuthors()) {
353
            foreach ($package->getAuthors() as $details) {
354
                $author = null;
355
356
                if (!$details->getName() && !$details->getEmail()) {
357
                    continue;
358
                }
359
360
                if ($details->getEmail()) {
361
                    $author = AddonAuthor::get()->filter('Email', $details->getEmail())->first();
362
                }
363
364
                if (!$author && $details->getHomepage()) {
365
                    $author = AddonAuthor::get()
366
                    ->filter('Name', $details->getName())
367
                    ->filter('Homepage', $details->getHomepage())
368
                    ->first();
369
                }
370
371
                if (!$author && $details->getName()) {
372
                    $author = AddonAuthor::get()
373
                    ->filter('Name', $details->getName())
374
                    ->filter('Versions.Addon.Name', $package->getName())
375
                    ->first();
376
                }
377
378
                if (!$author) {
379
                    $author = new AddonAuthor();
380
                }
381
382
                if ($details->getName()) {
383
                    $author->Name = $details->getName();
384
                }
385
                if ($details->getEmail()) {
386
                    $author->Email = $details->getEmail();
387
                }
388
                if ($details->getHomepage()) {
389
                    $author->Homepage = $details->getHomepage();
390
                }
391
392
                        //to-do not supported by API
393
                        //if(isset($details['role'])) $author->Role = $details['role'];
394
395
                $version->Authors()->add($author->write());
0 ignored issues
show
Documentation Bug introduced by
The method Authors does not exist on object<AddonVersion>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
396
            }
397
        }
398
    }
399
400
    /**
401
     * Get the list of SilverStripe versions
402
     *
403
     * @return DataList
404
     */
405
    public function getSilverStripeVersions()
406
    {
407
        return $this->silverstripes;
408
    }
409
410
    /**
411
     * Set the list of SilverStripeVersions
412
     *
413
     * @param  DataList $versions
414
     * @return $this
415
     */
416
    public function setSilverStripeVersions(DataList $versions)
417
    {
418
        $this->silverstripes = $versions;
0 ignored issues
show
Documentation Bug introduced by
It seems like $versions of type object<DataList> is incompatible with the declared type array<integer,object<SilverStripeVersion>> of property $silverstripes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
419
        return $this;
420
    }
421
}
422