Completed
Push — master ( 9e57a1...c5ae65 )
by Tyler
02:42
created

License::error()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
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\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
     * @param boolean $add
54
     * @return void
55
     */
56
    final public function allocate($quantity, $add = false)
57
    {
58
        $remaining = $this->remaining();
59
        if ($remaining < $quantity) {
60
            if(!$add) {
61
                $this->error($remaining, $quantity);
62
            } else {
63
                $this->add($quantity - $remaining);
64
            }
65
        }
66
    }
67
    
68
    /**
69
     * Called when there are not enough licenses available
70
     *
71
     * @param [type] $remaining
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
72
     * @param [type] $quantity
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
73
     * @return void
74
     */
75
    protected function error($remaining, $quantity)
76
    {
77
        throw new LicenseException($this->message($remaining, $quantity));
78
    }
79
80
    /**
81
     * Returns the difference between the maximum amount licenses and what you are trying to limit
82
     *
83
     * @return int
84
     */
85
    public function remaining()
86
    {
87
        return max($this->maximum() - $this->used(), 0);
88
    }
89
90
    /**
91
     * Returns the maximum amount of licenses
92
     *
93
     * @return int
94
     */
95
    public function maximum()
96
    {
97
        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...
98
    }
99
100
    /**
101
     * Returns the human readable error string when there are not enough licenses available.
102
     *
103
     * @param int $remaining Number of licenses available.
104
     * @param int $quantity Number of licenses trying to allocate.
105
     * @return string
106
     */
107
    protected function message($remaining, $quantity)
108
    {
109
        return "There are not enough licenses available. Tried to allocate {$quantity} but there are only {$remaining} available.";
110
    }
111
112
    /**
113
     * Returns human readable string for this license
114
     *
115
     * @return string
116
     */
117
    abstract public function name();
118
119
    /**
120
     * Returns the current amount of licenses in use
121
     *
122
     * @return int
123
     */
124
    abstract public function used();
125
126
    /**
127
     * Called before adding to the license count.
128
     * 
129
     * @param int $quantity
130
     * @return void
131
     */
132
    abstract protected function adding($quantity);
133
134
    /**
135
     * Called after adding to the license count
136
     *
137
     * @param int $quantity
138
     * @return void
139
     */
140
    abstract protected function added($quantity);
141
142
    /**
143
     * Called before subtracting the license count
144
     *
145
     * @param int $quantity
146
     * @return void
147
     */
148
    abstract protected function subtracting($quantity);
149
150
    /**
151
     * Called after subtracting the license count
152
     * 
153
     * @param int $quantity
154
     * @return void
155
     */
156
    abstract protected function subtracted($quantity);
157
158
    /**
159
     * Add more licenses
160
     *
161
     * @param int $quantity
162
     * @return boolean
163
     */
164
    final public function add($quantity = 1)
165
    {
166
        if (!is_int($quantity) || $quantity < 0) {
167
            throw new LicenseException("Quantity must be a positive integer.");
168
        }
169
170
        $this->adding($quantity);
171
172
        $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...
173
        $this->model->save();
174
175
        $this->added($quantity);
176
        
177
        return true;
178
    }
179
180
    /**
181
     * Subtract licenses
182
     *
183
     * @param int $quantity
184
     * @return boolean
185
     */
186
    final public function sub($quantity = 1)
187
    {
188
        if (!is_int($quantity) || $quantity < 0) {
189
            throw new LicenseException("Quantity must be a positive integer.");
190
        }
191
192
        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...
193
            throw new LicenseException("You cannot remove more licenses than you have available.");
194
        }
195
196
        $this->subtracting($quantity);
197
198
        $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...
199
        $this->model->save();
200
201
        $this->subtracted($quantity);
202
        
203
        return true;
204
    }
205
206
    /**
207
     * Set the amount of licenses
208
     *
209
     * @param int $quantity
210
     * @return boolean
211
     */
212
    final public function set($quantity)
213
    {
214
        if (!is_int($quantity) || $quantity < 0) {
215
            throw new LicenseException("Quantity must be a positive integer.");
216
        }
217
218
        $difference = $quantity - $this->maximum();
219
220
        if ($difference < 0) {
221
            return $this->sub(abs($difference));
222
        } else {
223
            return $this->add($difference);
224
        }
225
    }
226
}
227