Completed
Push — master ( 9abbc7...a687e5 )
by Fabrizio
03:03
created

NotificationManager   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 261
Duplicated Lines 13.03 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 10
Bugs 5 Features 2
Metric Value
wmc 22
c 10
b 5
f 2
lcom 1
cbo 3
dl 34
loc 261
rs 10

17 Methods

Rating   Name   Duplication   Size   Complexity  
A deleteByCategory() 0 4 1
A getLastNotification() 0 4 1
A getLastNotificationByCategory() 0 4 1
A __construct() 0 4 1
A entity() 0 6 1
A find() 0 11 2
A readOne() 0 6 1
A readLimit() 0 4 1
A readAll() 0 4 1
A delete() 0 4 1
A deleteLimit() 0 4 1
A deleteAll() 0 4 1
A getNotRead() 16 16 3
A getAll() 16 16 3
A sendOne() 0 4 1
A sendMultiple() 0 4 1
A countNotRead() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Fenos\Notifynder\Notifications;
4
5
use Closure;
6
use Fenos\Notifynder\Contracts\NotificationDB;
7
use Fenos\Notifynder\Contracts\NotifynderNotification;
8
use Fenos\Notifynder\Exceptions\NotificationNotFoundException;
9
use Fenos\Notifynder\Models\Notification as NotificationModel;
10
use Illuminate\Pagination\LengthAwarePaginator;
11
12
/**
13
 * Class NotifynderNotification.
14
 *
15
 * The notification manager is responsible to manage the CRUD operations
16
 * of the notifications.
17
 */
18
class NotificationManager implements NotifynderNotification
19
{
20
    /**
21
     * @var NotificationDB
22
     */
23
    protected $notifynderRepo;
24
25
    /**
26
     * @var string | null
27
     */
28
    protected $entity;
29
30
    /**
31
     * @param NotificationDB $notifynderRepo
32
     */
33
    public function __construct(NotificationDB $notifynderRepo)
34
    {
35
        $this->notifynderRepo = $notifynderRepo;
36
    }
37
38
    /**
39
     * Set the entity for polymorphic.
40
     *
41
     * @param $name
42
     * @return $this
43
     */
44
    public function entity($name)
45
    {
46
        $this->entity = $name;
47
48
        return $this;
49
    }
50
51
    /**
52
     * Find a notification by ID.
53
     *
54
     * @param $notificationId
55
     * @return NotificationModel|\Illuminate\Database\Eloquent\Model|static
56
     * @throws \Fenos\Notifynder\Exceptions\NotificationNotFoundException
57
     */
58
    public function find($notificationId)
59
    {
60
        $notification = $this->notifynderRepo->find($notificationId);
61
62
        if (is_null($notification)) {
63
            $error = 'Notification Not found';
64
            throw new NotificationNotFoundException($error);
65
        }
66
67
        return $notification;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $notification; (Illuminate\Database\Eloq...ontracts\NotificationDB) is incompatible with the return type declared by the interface Fenos\Notifynder\Contrac...ynderNotification::find of type Illuminate\Database\Eloq...\NotifynderNotification.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
68
    }
69
70
    /**
71
     * Make read one notification giving
72
     * the ID of it.
73
     *
74
     * @param $notificationId
75
     * @return bool|\Fenos\Notifynder\Models\Notification
76
     */
77
    public function readOne($notificationId)
78
    {
79
        $notification = $this->find($notificationId);
80
81
        return $this->notifynderRepo->readOne($notification);
0 ignored issues
show
Documentation introduced by
$notification is of type object<Illuminate\Databa...ntracts\NotificationDB>, but the function expects a object<Fenos\Notifynder\Models\Notification>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
82
    }
83
84
    /**
85
     * Read notifications in base the number
86
     * Given.
87
     *
88
     * @param         $toId
89
     * @param         $numbers
90
     * @param  string $order
91
     * @return mixed
92
     */
93
    public function readLimit($toId, $numbers, $order = 'ASC')
94
    {
95
        return $this->notifynderRepo->readLimit($toId, $this->entity, $numbers, $order);
96
    }
97
98
    /**
99
     * Read all notification of the
100
     * given entity.
101
     *
102
     * @param $toId
103
     * @return Number
104
     */
105
    public function readAll($toId)
106
    {
107
        return $this->notifynderRepo->readAll($toId, $this->entity);
108
    }
109
110
    /**
111
     * Delete a notification giving the id
112
     * of it.
113
     *
114
     * @param $notificationId
115
     * @return bool
116
     */
117
    public function delete($notificationId)
118
    {
119
        return $this->notifynderRepo->delete($notificationId);
120
    }
121
122
    /**
123
     * Delete numbers of notifications equals
124
     * to the number passing as 2 parameter of
125
     * the current user.
126
     *
127
     * @param $entityId
128
     * @param $number
129
     * @param $order
130
     * @return mixed
131
     */
132
    public function deleteLimit($entityId, $number, $order = 'asc')
133
    {
134
        return $this->notifynderRepo->deleteLimit($entityId, $this->entity, $number, $order);
135
    }
136
137
    /**
138
     * Delete all notification of a given
139
     * Entity.
140
     *
141
     * @param $entityId
142
     * @return bool
143
     */
144
    public function deleteAll($entityId)
145
    {
146
        return $this->notifynderRepo->deleteAll($entityId, $this->entity);
147
    }
148
149
    /**
150
     * Delete All notifications from a
151
     * defined category.
152
     *
153
     * @param $categoryName string
154
     * @param $expired Bool
155
     * @return bool
156
     */
157
    public function deleteByCategory($categoryName, $expired = false)
158
    {
159
        return $this->notifynderRepo->deleteByCategory($categoryName, $expired);
160
    }
161
162
    /**
163
     * Get notifications not read
164
     * of the entity given.
165
     *
166
     * @param           $toId
167
     * @param           $limit
168
     * @param  int|null $paginate
169
     * @param  string   $orderDate
170
     * @param Closure   $filterScope
171
     * @return mixed
172
     */
173 View Code Duplication
    public function getNotRead($toId, $limit = null, $paginate = null, $orderDate = 'desc', Closure $filterScope = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
174
    {
175
        $notifications = $this->notifynderRepo->getNotRead(
176
            $toId, $this->entity,
177
            $limit, $paginate, $orderDate,
178
            $filterScope
179
        );
180
181
        if (is_int(intval($paginate)) && $paginate) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $paginate of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
182
            return new LengthAwarePaginator($notifications->parse(), $notifications->total(), $limit, $paginate, [
183
                'path' => LengthAwarePaginator::resolveCurrentPath(),
184
            ]);
185
        }
186
187
        return $notifications->parse();
188
    }
189
190
    /**
191
     * Get All notifications.
192
     *
193
     * @param           $toId
194
     * @param           $limit
195
     * @param  int|null $paginate
196
     * @param  string   $orderDate
197
     * @param Closure   $filterScope
198
     * @return mixed
199
     */
200 View Code Duplication
    public function getAll($toId, $limit = null, $paginate = null, $orderDate = 'desc', Closure $filterScope = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
    {
202
        $notifications = $this->notifynderRepo->getAll(
203
            $toId, $this->entity,
204
            $limit, $paginate, $orderDate,
205
            $filterScope
206
        );
207
208
        if (is_int(intval($paginate)) && $paginate) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $paginate of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
209
            return new LengthAwarePaginator($notifications->parse(), $notifications->total(), $limit, $paginate, [
210
                'path' => LengthAwarePaginator::resolveCurrentPath(),
211
            ]);
212
        }
213
214
        return $notifications->parse();
215
    }
216
217
    /**
218
     * Get last notification of the
219
     * given entity.
220
     *
221
     * @param         $toId
222
     * @param Closure $filterScope
223
     * @return mixed
224
     */
225
    public function getLastNotification($toId, Closure $filterScope = null)
226
    {
227
        return $this->notifynderRepo->getLastNotification($toId, $this->entity, $filterScope);
228
    }
229
230
    /**
231
     * Get last notification of the
232
     * given entity of the specific category.
233
     *
234
     * @param         $category
235
     * @param         $toId
236
     * @param Closure $filterScope
237
     * @return mixed
238
     */
239
    public function getLastNotificationByCategory($category, $toId, Closure $filterScope = null)
240
    {
241
        return $this->notifynderRepo->getLastNotificationByCategory($category, $toId, $this->entity, $filterScope);
242
    }
243
244
    /**
245
     * Send single notification.
246
     *
247
     * @param  array  $info
248
     * @return static
249
     */
250
    public function sendOne(array $info)
251
    {
252
        return $this->notifynderRepo->storeSingle($info);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->notifynderRepo->storeSingle($info); (Fenos\Notifynder\Models\Notification) is incompatible with the return type declared by the interface Fenos\Notifynder\Contrac...erNotification::sendOne of type Fenos\Notifynder\Contracts\NotifynderNotification.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
253
    }
254
255
    /**
256
     * Send multiple notifications.
257
     *
258
     * @param  array $info
259
     * @return mixed
260
     */
261
    public function sendMultiple(array $info)
262
    {
263
        return $this->notifynderRepo->storeMultiple($info);
264
    }
265
266
    /**
267
     * Get number of notification
268
     * not read.
269
     *
270
     * @param         $toId
271
     * @param Closure $filterScope
272
     * @return mixed
273
     */
274
    public function countNotRead($toId, Closure $filterScope = null)
275
    {
276
        return $this->notifynderRepo->countNotRead($toId, $this->entity, $filterScope);
277
    }
278
}
279