Completed
Push — master ( 09d0a5...42fa8d )
by Tyler
02:25
created

License::set()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 3
nop 1
1
<?php
2
3
namespace Tylercd100\License;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Tylercd100\License\Exceptions\LicenseException;
7
use Tylercd100\License\Models\License as LicenseModel;
8
use Tylercd100\License\Traits\HasLicenses;
9
10
abstract class License
11
{
12
    /**
13
     * Owner of the licenses
14
     *
15
     * @var Model
16
     */
17
    protected $owner;
18
19
    /**
20
     * The database model for tracking licenses
21
     *
22
     * @var LicenseModel
23
     */
24
    protected $model;
25
26
    /**
27
     * The default starting amount for the license
28
     *
29
     * @var int
30
     */
31
    protected $default = 0;
32
33
    function __construct(Model $owner)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
34
    {
35
        if (!in_array(HasLicenses::class, class_uses($owner))) {
36
            throw new LicenseException("The owner must use the trait: ".HasLicenses::class);
37
        }
38
39
        $this->owner = $owner;
40
        $this->model = LicenseModel::firstOrCreate([
41
            "owner_type" => get_class($owner),
42
            "owner_id" => $owner->id,
43
            "license" => get_class($this),
44
        ], [
45
            "quantity" => $this->default,
46
        ]);
47
    }
48
49
    /**
50
     * Throws exception if there are not enough licenses available
51
     *
52
     * @param int $quantity
53
     * @return void
54
     */
55
    public function check($quantity)
56
    {
57
        $remaining = $this->remaining();
58
        if ($remaining < $quantity) {
59
            throw new LicenseException($this->message($remaining, $quantity));
60
        }
61
    }
62
63
    /**
64
     * Returns the difference between the maximum amount licenses and what you are trying to limit
65
     *
66
     * @return int
67
     */
68
    public function remaining()
69
    {
70
        return max($this->maximum() - $this->used(), 0);
71
    }
72
73
    /**
74
     * Returns the maximum amount of licenses
75
     *
76
     * @return int
77
     */
78
    public function maximum()
79
    {
80
        return $this->model->quantity;
0 ignored issues
show
Documentation introduced by
The property quantity does not exist on object<Tylercd100\License\Models\License>. 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...
81
    }
82
83
    /**
84
     * Returns the human readable error string when there are not enough licenses available.
85
     *
86
     * @param int $remaining Number of licenses available.
87
     * @param int $quantity Number of licenses trying to allocate.
88
     * @return string
89
     */
90
    protected function message($remaining, $quantity)
91
    {
92
        return "There are not enough licenses available. Tried to allocate {$quantity} but there are only {$remaining} available.";
93
    }
94
95
    /**
96
     * Returns the current amount of licenses in use
97
     *
98
     * @return int
99
     */
100
    abstract public function used();
101
102
    /**
103
     * Called before adding to the license count.
104
     * 
105
     * Should return true to proceed or false to cancel operation
106
     * 
107
     * @return boolean
108
     */
109
    abstract protected function adding();
110
111
    /**
112
     * Called after adding to the license count
113
     *
114
     * @return void
115
     */
116
    abstract protected function added();
117
118
    /**
119
     * Called before subtracting the license count
120
     *
121
     * @return void
122
     */
123
    abstract protected function subtracting();
124
125
    /**
126
     * Called after subtracting the license count
127
     * 
128
     * Should return true to proceed or false to cancel operation
129
     *
130
     * @return void
131
     */
132
    abstract protected function subtracted();
133
134
    /**
135
     * Add more licenses
136
     *
137
     * @param int $quantity
138
     * @return boolean
139
     */
140
    final public function add($quantity = 1)
141
    {
142
        if (!is_int($quantity) || $quantity <= 0) {
143
            throw new LicenseExeception("Quantity must be a positive integer.");
144
        }
145
146
        $this->adding($quantity);
0 ignored issues
show
Unused Code introduced by
The call to License::adding() has too many arguments starting with $quantity.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
147
148
        $this->model->quantity += $quantity;
0 ignored issues
show
Documentation introduced by
The property quantity does not exist on object<Tylercd100\License\Models\License>. 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
        $this->model->save();
150
151
        $this->added($quantity);
0 ignored issues
show
Unused Code introduced by
The call to License::added() has too many arguments starting with $quantity.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
152
        
153
        return true;
154
    }
155
156
    /**
157
     * Subtract licenses
158
     *
159
     * @param int $quantity
160
     * @return boolean
161
     */
162
    final public function sub($quantity = 1)
163
    {
164
        if (!is_int($quantity) || $quantity <= 0) {
165
            throw new LicenseExeception("Quantity must be a positive integer.");
166
        }
167
168
        if ($this->model->quantity - $quantity < 0) {
0 ignored issues
show
Documentation introduced by
The property quantity does not exist on object<Tylercd100\License\Models\License>. 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...
169
            throw new LicenseExeception("You cannot remove more licenses than you have available.");
170
        }
171
172
        $this->subtracting($quantity);
0 ignored issues
show
Unused Code introduced by
The call to License::subtracting() has too many arguments starting with $quantity.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
173
174
        $this->model->quantity -= $quantity;
0 ignored issues
show
Documentation introduced by
The property quantity does not exist on object<Tylercd100\License\Models\License>. 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...
175
        $this->model->save();
176
177
        $this->subtracted($quantity);
0 ignored issues
show
Unused Code introduced by
The call to License::subtracted() has too many arguments starting with $quantity.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
178
        
179
        return true;
180
    }
181
182
    /**
183
     * Set the amount of licenses
184
     *
185
     * @param int $quantity
186
     * @return boolean
187
     */
188
    final public function set($quantity)
189
    {
190
        if (!is_int($quantity) || $quantity <= 0) {
191
            throw new LicenseExeception("Quantity must be a positive integer.");
192
        }
193
194
        $difference = $quantity - $this->maximum();
195
196
        if ($difference < 0) {
197
            return $this->sub(abs($difference));
198
        } else {
199
            return $this->add($difference);
200
        }
201
    }
202
}
203