This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Sagitarius29\LaravelSubscriptions\Traits; |
||
4 | |||
5 | use Carbon\Carbon; |
||
6 | use Illuminate\Database\Eloquent\Model; |
||
7 | use Illuminate\Database\Eloquent\Relations\MorphMany; |
||
8 | use Sagitarius29\LaravelSubscriptions\Contracts\PlanContract; |
||
9 | use Sagitarius29\LaravelSubscriptions\Contracts\PlanIntervalContract; |
||
10 | use Sagitarius29\LaravelSubscriptions\Contracts\SubscriptionContact; |
||
11 | use Sagitarius29\LaravelSubscriptions\Entities\PlanInterval; |
||
12 | use Sagitarius29\LaravelSubscriptions\Entities\Subscription; |
||
13 | use Sagitarius29\LaravelSubscriptions\Exceptions\SubscriptionErrorException; |
||
14 | use Sagitarius29\LaravelSubscriptions\PlanFeature; |
||
15 | |||
16 | trait HasSubscriptions |
||
17 | { |
||
18 | /** |
||
19 | * @param PlanContract|PlanIntervalContract $planOrInterval |
||
20 | * @return Model|SubscriptionContact |
||
21 | */ |
||
22 | public function subscribeTo($planOrInterval): SubscriptionContact |
||
23 | { |
||
24 | if ($planOrInterval instanceof PlanContract) { |
||
25 | return $this->subscribeToPlan($planOrInterval); |
||
26 | } |
||
27 | |||
28 | return $this->subscribeToInterval($planOrInterval); |
||
29 | } |
||
30 | |||
31 | /** |
||
32 | * @param PlanContract $plan |
||
33 | * @return Model|SubscriptionContact |
||
34 | * @throws SubscriptionErrorException |
||
35 | */ |
||
36 | public function subscribeToPlan(PlanContract $plan): SubscriptionContact |
||
37 | { |
||
38 | if ($plan->isDisabled()) { |
||
39 | throw new SubscriptionErrorException( |
||
40 | 'This plan has been disabled, please subscribe to other plan.' |
||
41 | ); |
||
42 | } |
||
43 | |||
44 | if ($this->subscriptions()->unfinished()->count() >= 2) { |
||
45 | throw new SubscriptionErrorException('You are changed to other plan previously'); |
||
46 | } |
||
47 | |||
48 | if ($plan->hasManyIntervals()) { |
||
49 | throw new SubscriptionErrorException( |
||
50 | 'This plan has many intervals, please use subscribeToInterval() function' |
||
51 | ); |
||
52 | } |
||
53 | |||
54 | $currentSubscription = $this->getActiveSubscription(); |
||
55 | $start_at = null; |
||
0 ignored issues
–
show
|
|||
56 | $end_at = null; |
||
0 ignored issues
–
show
$end_at is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
57 | |||
58 | if ($currentSubscription == null) { |
||
59 | $start_at = now(); |
||
60 | } else { |
||
61 | $start_at = $currentSubscription->getExpirationDate(); |
||
0 ignored issues
–
show
The method
getExpirationDate does only exist in Sagitarius29\LaravelSubs...cts\SubscriptionContact , but not in Illuminate\Database\Eloquent\Model .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
62 | } |
||
63 | |||
64 | if ($plan->isFree()) { |
||
65 | $end_at = null; |
||
66 | } else { |
||
67 | $end_at = $this->calculateExpireDate($start_at, optional($plan->intervals())->first()); |
||
68 | } |
||
69 | |||
70 | $subscription = Subscription::make($plan, $start_at, $end_at); |
||
71 | $subscription = $this->subscriptions()->save($subscription); |
||
72 | |||
73 | return $subscription; |
||
74 | } |
||
75 | |||
76 | public function subscriptions(): MorphMany |
||
77 | { |
||
78 | return $this->morphMany(config('subscriptions.entities.plan_subscription'), 'subscriber'); |
||
0 ignored issues
–
show
It seems like
morphMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
79 | } |
||
80 | |||
81 | /** |
||
82 | * @return SubscriptionContact|Model|null |
||
83 | */ |
||
84 | public function getActiveSubscription(): ?SubscriptionContact |
||
85 | { |
||
86 | return $this->subscriptions() |
||
87 | ->current() |
||
88 | ->first(); |
||
89 | } |
||
90 | |||
91 | private function calculateExpireDate(Carbon $start_at, PlanIntervalContract $interval) |
||
92 | { |
||
93 | $end_at = Carbon::createFromTimestamp($start_at->timestamp); |
||
94 | |||
95 | switch ($interval->getType()) { |
||
96 | case PlanInterval::DAY: |
||
97 | return $end_at->addDays($interval->getUnit()); |
||
98 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
99 | case PlanInterval::MONTH: |
||
100 | return $end_at->addMonths($interval->getUnit()); |
||
101 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
102 | case PlanInterval::YEAR: |
||
103 | return $end_at->addYears($interval->getUnit()); |
||
104 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
105 | default: |
||
106 | throw new SubscriptionErrorException( |
||
107 | 'The interval \''.$interval->getType().'\' selected is not available.' |
||
108 | ); |
||
109 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
110 | } |
||
111 | } |
||
112 | |||
113 | public function subscribeToInterval(PlanIntervalContract $interval): SubscriptionContact |
||
114 | { |
||
115 | if ($interval->plan->isDisabled()) { |
||
0 ignored issues
–
show
Accessing
plan on the interface Sagitarius29\LaravelSubs...ts\PlanIntervalContract suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
![]() |
|||
116 | throw new SubscriptionErrorException( |
||
117 | 'This plan has been disabled, please subscribe to other plan.' |
||
118 | ); |
||
119 | } |
||
120 | |||
121 | if ($this->subscriptions()->unfinished()->count() >= 2) { |
||
122 | throw new SubscriptionErrorException('You are changed to other plan previously'); |
||
123 | } |
||
124 | |||
125 | $currentSubscription = $this->getActiveSubscription(); |
||
126 | $start_at = null; |
||
0 ignored issues
–
show
$start_at is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
127 | $end_at = null; |
||
0 ignored issues
–
show
$end_at is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
128 | |||
129 | if ($currentSubscription == null) { |
||
130 | $start_at = now(); |
||
131 | } else { |
||
132 | $start_at = $currentSubscription->getExpirationDate(); |
||
0 ignored issues
–
show
The method
getExpirationDate does only exist in Sagitarius29\LaravelSubs...cts\SubscriptionContact , but not in Illuminate\Database\Eloquent\Model .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
133 | } |
||
134 | |||
135 | $end_at = $this->calculateExpireDate($start_at, $interval); |
||
136 | |||
137 | $subscription = Subscription::make($interval->plan, $start_at, $end_at); |
||
0 ignored issues
–
show
Accessing
plan on the interface Sagitarius29\LaravelSubs...ts\PlanIntervalContract suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
![]() |
|||
138 | $subscription = $this->subscriptions()->save($subscription); |
||
139 | |||
140 | return $subscription; |
||
141 | } |
||
142 | |||
143 | public function changePlanTo(PlanContract $plan, PlanIntervalContract $interval = null) |
||
144 | { |
||
145 | if (! $this->hasActiveSubscription()) { |
||
146 | throw new SubscriptionErrorException('You need a subscription for upgrade to other.'); |
||
147 | } |
||
148 | |||
149 | if ($plan->hasManyIntervals() && $interval == null) { |
||
150 | throw new SubscriptionErrorException('The plan has many intervals, please indicate a interval.'); |
||
151 | } |
||
152 | |||
153 | if ($this->subscriptions()->unfinished()->count() >= 2) { |
||
154 | throw new SubscriptionErrorException('You are changed to other plan previously'); |
||
155 | } |
||
156 | |||
157 | $currentSubscription = $this->getActiveSubscription(); |
||
158 | $currentPlan = $currentSubscription->plan; |
||
159 | $currentIntervalPrice = $currentPlan->isFree() ? 0.00 : $currentPlan->getInterval()->getPrice(); |
||
160 | |||
161 | $toInterval = $plan->getInterval(); |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Sagitarius29\LaravelSubs...\Contracts\PlanContract as the method getInterval() does only exist in the following implementations of said interface: Sagitarius29\LaravelSubscriptions\Entities\Plan .
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
162 | |||
163 | if ($currentPlan->id == $plan->id) { |
||
0 ignored issues
–
show
Accessing
id on the interface Sagitarius29\LaravelSubs...\Contracts\PlanContract suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
![]() |
|||
164 | throw new SubscriptionErrorException('You can\'t change to same plan. You need change to other plan.'); |
||
165 | } |
||
166 | |||
167 | if ($interval !== null) { |
||
168 | $toInterval = $interval; |
||
169 | } |
||
170 | |||
171 | if ($currentIntervalPrice < $toInterval->getPrice()) { |
||
172 | return $this->upgradeTo($toInterval); |
||
173 | } |
||
174 | |||
175 | return $this->downgradeTo($toInterval); |
||
176 | } |
||
177 | |||
178 | public function hasActiveSubscription(): bool |
||
179 | { |
||
180 | return $this->subscriptions() |
||
181 | ->current() |
||
182 | ->exists(); |
||
183 | } |
||
184 | |||
185 | protected function upgradeTo(PlanIntervalContract $interval): SubscriptionContact |
||
186 | { |
||
187 | if (! $this->hasActiveSubscription()) { |
||
188 | throw new SubscriptionErrorException('You need a subscription for upgrade to other.'); |
||
189 | } |
||
190 | |||
191 | $this->forceUnsubscribe(); |
||
192 | |||
193 | return $this->subscribeToInterval($interval); |
||
194 | } |
||
195 | |||
196 | public function forceUnsubscribe() |
||
197 | { |
||
198 | $currentSubscription = $this->getActiveSubscription(); |
||
199 | if ($currentSubscription != null) { |
||
200 | $currentSubscription->end_at = now()->subSecond(); |
||
201 | $currentSubscription->cancelled_at = now(); |
||
202 | $currentSubscription->save(); |
||
0 ignored issues
–
show
The method
save does only exist in Illuminate\Database\Eloquent\Model , but not in Sagitarius29\LaravelSubs...cts\SubscriptionContact .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
203 | } |
||
204 | } |
||
205 | |||
206 | protected function downgradeTo(PlanIntervalContract $interval): SubscriptionContact |
||
207 | { |
||
208 | if (! $this->hasActiveSubscription()) { |
||
209 | throw new SubscriptionErrorException('You need a subscription for upgrade to other.'); |
||
210 | } |
||
211 | |||
212 | return $this->subscribeToInterval($interval); |
||
213 | } |
||
214 | |||
215 | public function renewSubscription(PlanIntervalContract $interval = null) |
||
216 | { |
||
217 | if ($this->subscriptions()->unfinished()->count() >= 2) { |
||
218 | throw new SubscriptionErrorException('You are changed to other plan previously'); |
||
219 | } |
||
220 | |||
221 | $currentSubscription = $this->getActiveSubscription(); |
||
222 | |||
223 | if ($interval === null) { |
||
224 | $plan = $currentSubscription->plan; |
||
225 | |||
226 | if ($plan->hasManyIntervals()) { |
||
227 | throw new SubscriptionErrorException( |
||
228 | 'The plan you want will subscribe has many intervals, please consider renew to a interval of plan' |
||
229 | ); |
||
230 | } |
||
231 | |||
232 | $interval = $plan->intervals()->first(); |
||
233 | } |
||
234 | |||
235 | $newExpireDate = $this->calculateExpireDate($currentSubscription->end_at, $interval); |
||
236 | |||
237 | $currentSubscription->end_at = $newExpireDate; |
||
238 | $currentSubscription->save(); |
||
0 ignored issues
–
show
The method
save does only exist in Illuminate\Database\Eloquent\Model , but not in Sagitarius29\LaravelSubs...cts\SubscriptionContact .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
239 | |||
240 | return $currentSubscription; |
||
241 | } |
||
242 | |||
243 | public function unsubscribe() |
||
244 | { |
||
245 | $currentSubscription = $this->getActiveSubscription(); |
||
246 | |||
247 | if (isset($currentSubscription)) { |
||
248 | $currentSubscription->cancelled_at = now(); |
||
249 | $currentSubscription->save(); |
||
0 ignored issues
–
show
The method
save does only exist in Illuminate\Database\Eloquent\Model , but not in Sagitarius29\LaravelSubs...cts\SubscriptionContact .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
250 | } |
||
251 | } |
||
252 | |||
253 | public function abilityFor(string $featureCode) |
||
254 | { |
||
255 | if (! array_key_exists($featureCode, config('subscriptions.default_features.features'))) { |
||
256 | throw new SubscriptionErrorException('The "'.$featureCode.'" is not available in the system.'); |
||
257 | } |
||
258 | |||
259 | $defaultFeature = config('subscriptions.default_features.features.'.$featureCode); |
||
260 | $activeSubscription = $this->getActiveSubscription(); |
||
261 | |||
262 | if ($activeSubscription == null) { |
||
263 | return $defaultFeature; |
||
264 | } |
||
265 | |||
266 | $feature = $activeSubscription->plan->getFeatureByCode($featureCode); |
||
267 | |||
268 | if ($feature == null) { |
||
269 | return $defaultFeature; |
||
270 | } |
||
271 | |||
272 | return $activeSubscription->plan->getFeatureByCode($featureCode)->getValue(); |
||
273 | } |
||
274 | |||
275 | public function abilitiesList() |
||
276 | { |
||
277 | $loadFeatures = config('subscriptions.default_features.features'); |
||
278 | $activeSubscription = $this->getActiveSubscription(); |
||
279 | |||
280 | if ($activeSubscription == null) { |
||
281 | return $loadFeatures; |
||
282 | } |
||
283 | |||
284 | $features = $activeSubscription->plan->features; |
||
285 | |||
286 | $features->each(function (PlanFeature $feature) use (&$loadFeatures) { |
||
287 | $loadFeatures[$feature->getCode()] = $feature->getValue(); |
||
288 | }); |
||
289 | |||
290 | return $loadFeatures; |
||
291 | } |
||
292 | |||
293 | public function getConsumables() |
||
294 | { |
||
295 | //TODO |
||
296 | } |
||
297 | } |
||
298 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.