Notification   C
last analyzed

Complexity

Total Complexity 63

Size/Duplication

Total Lines 511
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 63
c 1
b 0
f 0
lcom 1
cbo 3
dl 0
loc 511
ccs 155
cts 155
cp 1
rs 5.8893

36 Methods

Rating   Name   Duplication   Size   Complexity  
A setSessionManager() 0 6 1
A getSessionManager() 0 8 2
A getContainer() 0 11 2
A add() 0 18 4
A addInfo() 0 4 1
A addSuccess() 0 4 1
A addWarning() 0 4 1
A addError() 0 4 1
A __invoke() 0 8 3
A get() 0 8 2
A getAll() 0 6 1
A getInfo() 0 4 1
A getSuccess() 0 4 1
A getWarning() 0 4 1
A getError() 0 4 1
A has() 0 6 1
A hasInfo() 0 4 1
A hasSuccess() 0 4 1
A hasWarning() 0 4 1
A hasError() 0 4 1
A getCurrent() 0 10 2
A getAllCurrent() 0 11 2
A getCurrentInfo() 0 4 1
A getCurrentSuccess() 0 4 1
A getCurrentWarning() 0 4 1
A getCurrentError() 0 4 1
A hasCurrent() 0 6 1
A hasCurrentInfo() 0 4 1
A hasCurrentSuccess() 0 4 1
A hasCurrentWarning() 0 4 1
A hasCurrentError() 0 4 1
C __call() 0 31 7
A getNotificationsFromContainer() 0 16 4
A clearNotificationsFromContainer() 0 9 3
A clearCurrent() 0 19 4
A clear() 0 19 4

How to fix   Complexity   

Complex Class

Complex classes like Notification often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Notification, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license.
17
 */
18
19
namespace SzmNotification\Controller\Plugin;
20
21
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
22
use Zend\Session\ManagerInterface as Manager;
23
use Zend\Session\Container;
24
use Zend\Stdlib\SplQueue;
25
26
class Notification extends AbstractPlugin
27
{
28
    /**
29
     * Namespace for info notifications
30
     */
31
    const NAMESPACE_INFO = 'info';
32
33
    /**
34
     * Namespace for success notifications
35
     */
36
    const NAMESPACE_SUCCESS = 'success';
37
38
    /**
39
     * Namespace for warning notifications
40
     */
41
    const NAMESPACE_WARNING = 'warning';
42
43
    /**
44
     * Namespace for error notifications
45
     */
46
    const NAMESPACE_ERROR = 'error';
47
48
    /**
49
     * @var Container
50
     */
51
    protected $container;
52
53
    /**
54
     * @var Manager
55
     */
56
    protected $sessionManager;
57
58
    /**
59
     * @var array
60
     */
61
    protected $notifications = [];
62
63
    /**
64
     * @var bool
65
     */
66
    protected $isAdded = false;
67
68
    /**
69
     * @var array
70
     */
71
    protected $customMethods = [
72
        'add',
73
        'get',
74
        'getcurrent',
75
        'has',
76
        'hascurrent'
77
    ];
78
79
    /**
80
     * @param Manager $manager
81
     * @return $this
82
     */
83 4
    public function setSessionManager(Manager $manager)
84
    {
85 4
        $this->sessionManager = $manager;
86
87 4
        return $this;
88
    }
89
90
    /**
91
     * @return Manager
92
     */
93 4
    public function getSessionManager()
94
    {
95 4
        if (!$this->sessionManager instanceof Manager) {
96 4
            $this->setSessionManager(Container::getDefaultManager());
97 4
        }
98
99 4
        return $this->sessionManager;
100
    }
101
102
    /**
103
     * @return Container
104
     */
105 4
    public function getContainer()
106
    {
107 4
        if ($this->container instanceof Container) {
108 3
            return $this->container;
109
        }
110
111 4
        $manager = $this->getSessionManager();
112 4
        $this->container = new Container('notifications', $manager);
113
114 4
        return $this->container;
115
    }
116
117
    /**
118
     * @param $type
119
     * @param $message
120
     * @param int $hops
121
     * @return $this
122
     */
123 5
    public function add($type, $message, $hops = 1)
124
    {
125 5
        $container = $this->getContainer();
126
127 5
        if (!$this->isAdded) {
128 5
            $this->getNotificationsFromContainer();
129 5
            $container->setExpirationHops($hops);
130 5
        }
131
132 5
        if (!isset($container->{$type}) || !$container->{$type} instanceof SplQueue) {
133 5
            $container->{$type} = new SplQueue();
134 5
        }
135
136 5
        $container->{$type}->push($message);
137 5
        $this->isAdded = true;
138
139 5
        return $this;
140
    }
141
142
    /**
143
     * @param $message
144
     * @return $this
145
     */
146 1
    public function addInfo($message)
147
    {
148 1
        return $this->add(self::NAMESPACE_INFO, $message);
149
    }
150
151
    /**
152
     * @param $message
153
     * @return $this
154
     */
155 1
    public function addSuccess($message)
156
    {
157 1
        return $this->add(self::NAMESPACE_SUCCESS, $message);
158
    }
159
160
    /**
161
     * @param $message
162
     * @return $this
163
     */
164 1
    public function addWarning($message)
165
    {
166 1
        return $this->add(self::NAMESPACE_WARNING, $message);
167
    }
168
169
    /**
170
     * @param $message
171
     * @return $this
172
     */
173 1
    public function addError($message)
174
    {
175 1
        return $this->add(self::NAMESPACE_ERROR, $message);
176
    }
177
178
    /**
179
     * @param $type
180
     * @param $message
181
     * @return $this
182
     */
183 2
    public function __invoke($type = null, $message = null)
184
    {
185 2
        if (!$type || !$message) {
186 1
            return $this;
187
        }
188
189 1
        return $this->add($type, $message);
190
    }
191
192
    /**
193
     * @param $namespace
194
     * @return array
195
     */
196 4
    public function get($namespace)
197
    {
198 4
        if ($this->has($namespace)) {
199 3
            return $this->notifications[$namespace]->toArray();
200
        }
201
202 1
        return [];
203
    }
204
205
    /**
206
     * @return array
207
     */
208 1
    public function getAll()
209
    {
210 1
        $this->getNotificationsFromContainer();
211
212 1
        return $this->notifications;
213
    }
214
215
    /**
216
     * @return array
217
     */
218 1
    public function getInfo()
219
    {
220 1
        return $this->get(self::NAMESPACE_INFO);
221
    }
222
223
    /**
224
     * @return array
225
     */
226 1
    public function getSuccess()
227
    {
228 1
        return $this->get(self::NAMESPACE_SUCCESS);
229
    }
230
231
    /**
232
     * @return array
233
     */
234 1
    public function getWarning()
235
    {
236 1
        return $this->get(self::NAMESPACE_WARNING);
237
    }
238
239
    /**
240
     * @return array
241
     */
242 1
    public function getError()
243
    {
244 1
        return $this->get(self::NAMESPACE_ERROR);
245
    }
246
247
    /**
248
     * @param $namespace
249
     * @return bool
250
     */
251 3
    public function has($namespace)
252
    {
253 3
        $this->getNotificationsFromContainer();
254
255 3
        return isset($this->notifications[$namespace]);
256
    }
257
258
    /**
259
     * @return bool
260
     */
261 1
    public function hasInfo()
262
    {
263 1
        return $this->has(self::NAMESPACE_INFO);
264
    }
265
266
    /**
267
     * @return bool
268
     */
269 1
    public function hasSuccess()
270
    {
271 1
        return $this->has(self::NAMESPACE_SUCCESS);
272
    }
273
274
    /**
275
     * @return bool
276
     */
277 1
    public function hasWarning()
278
    {
279 1
        return $this->has(self::NAMESPACE_WARNING);
280
    }
281
282
    /**
283
     * @return bool
284
     */
285 1
    public function hasError()
286
    {
287 1
        return $this->has(self::NAMESPACE_ERROR);
288
    }
289
290
    /**
291
     * @param $namespace
292
     * @return array|mixed
293
     */
294 3
    public function getCurrent($namespace)
295
    {
296 3
        if ($this->hasCurrent($namespace)) {
297 2
            $container = $this->getContainer();
298
299 2
            return $container->{$namespace}->toArray();
300
        }
301
302 1
        return [];
303
    }
304
305
    /**
306
     * Get all current notifications
307
     *
308
     * @return array
309
     */
310 1
    public function getAllCurrent()
311
    {
312 1
        $notifications = [];
313 1
        $container = $this->getContainer();
314
315 1
        foreach ($container as $namespace => $notification) {
316 1
            $notifications[$namespace] = $this->getCurrent($namespace);
317 1
        }
318
319 1
        return $notifications;
320
    }
321
322
    /**
323
     * Get info notifications added during this request
324
     *
325
     * @return array|mixed
326
     */
327 1
    public function getCurrentInfo()
328
    {
329 1
        return $this->getCurrent(self::NAMESPACE_INFO);
330
    }
331
332
    /**
333
     * Get success notifications added during this request
334
     *
335
     * @return array|mixed
336
     */
337 1
    public function getCurrentSuccess()
338
    {
339 1
        return $this->getCurrent(self::NAMESPACE_SUCCESS);
340
    }
341
342
    /**
343
     * Get warning notifications added during this request
344
     *
345
     * @return array|mixed
346
     */
347 1
    public function getCurrentWarning()
348
    {
349 1
        return $this->getCurrent(self::NAMESPACE_WARNING);
350
    }
351
352
    /**
353
     * Get error notifications added during this request
354
     *
355
     * @return array|mixed
356
     */
357 1
    public function getCurrentError()
358
    {
359 1
        return $this->getCurrent(self::NAMESPACE_ERROR);
360
    }
361
362
    /**
363
     * @param $namespace
364
     * @return bool
365
     */
366 2
    public function hasCurrent($namespace)
367
    {
368 2
        $container = $this->getContainer();
369
370 2
        return isset($container->{$namespace});
371
    }
372
373
    /**
374
     * Check if info notifications have been added during this request
375
     *
376
     * @return bool
377
     */
378 1
    public function hasCurrentInfo()
379
    {
380 1
        return $this->hasCurrent(self::NAMESPACE_INFO);
381
    }
382
383
    /**
384
     * Check if success notifications have been added during this request
385
     *
386
     * @return bool
387
     */
388 1
    public function hasCurrentSuccess()
389
    {
390 1
        return $this->hasCurrent(self::NAMESPACE_SUCCESS);
391
    }
392
393
    /**
394
     * Check if warning notifications have been added during this request
395
     *
396
     * @return bool
397
     */
398 1
    public function hasCurrentWarning()
399
    {
400 1
        return $this->hasCurrent(self::NAMESPACE_WARNING);
401
    }
402
403
    /**
404
     * Check if error notifications have been added during this request
405
     *
406
     * @return bool
407
     */
408 1
    public function hasCurrentError()
409
    {
410 1
        return $this->hasCurrent(self::NAMESPACE_ERROR);
411
    }
412
413
    /**
414
     * @param $name
415
     * @param $arguments
416
     * @return mixed
417
     */
418 7
    public function __call($name, $arguments)
419
    {
420
        // we take first 3 chars from called method
421 7
        $length = 3;
422 7
        $name = strtolower($name);
423 7
        if (strpos($name, 'current')) {
424 2
            $length += strlen('current');
425 2
        }
426
427 7
        $method = substr($name, 0, $length);
428 7
        if (!in_array($method, $this->customMethods)) {
429 2
            return false;
430
        }
431
432 6
        $namespace = substr($name, $length);
433 6
        if ($method !== 'add') {
434 4
            return $this->$method($namespace);
435
        }
436
437
        // If user called add method then we have to check if he provided notification text
438 6
        if (!isset($arguments[0]) || !is_string($arguments[0])) {
439 1
            throw new \InvalidArgumentException(sprintf(
440 1
                '%s method must contains notification text, %s given.',
441 1
                $name,
442 1
                isset($arguments[0]) ? gettype($arguments[0]) : null
443 1
            ));
444
        }
445
446 5
        $this->$method($namespace, $arguments[0]);
447 5
        return $this;
448
    }
449
450
    /**
451
     * Clear notifications from container
452
     */
453 4
    protected function getNotificationsFromContainer()
454
    {
455 4
        if (!empty($this->notifications) || $this->isAdded) {
456 1
            return;
457
        }
458
459 4
        $container = $this->getContainer();
460 4
        $namespaces = [];
461
462 4
        foreach ($container as $namespace => $notification) {
463 3
            $this->notifications[$namespace] = $notification;
464 3
            $namespaces[] = $namespace;
465 4
        }
466
467 4
        $this->clearNotificationsFromContainer($namespaces);
468 4
    }
469
470
    /**
471
     * @param $namespaces
472
     */
473 4
    protected function clearNotificationsFromContainer($namespaces)
474
    {
475 4
        $namespaces = is_array($namespaces) ? $namespaces : [$namespaces];
476 4
        $container = $this->getContainer();
477
478 4
        foreach ($namespaces as $namespace) {
479 3
            unset($container->{$namespace});
480 4
        }
481 4
    }
482
483
    /**
484
     * Clear notifications from container if namespace is provided or clear all notifications
485
     * added during this request if namespace is not provided.
486
     *
487
     * @param null $namespace
488
     * @return bool
489
     */
490 3
    public function clearCurrent($namespace = null)
491
    {
492 3
        $container = $this->getContainer();
493
494 3
        if ($namespace) {
495 2
            if (!$container->offsetExists($namespace)) {
496 1
                return false;
497
            }
498
499 1
            unset($container->{$namespace});
500 1
            return true;
501
        }
502
503 1
        foreach ($container as $namespace => $notifications) {
504 1
            $container->offsetUnset($namespace);
505 1
        }
506
507 1
        return true;
508
    }
509
510
    /**
511
     * Clear notifications from previous request by provided namespace or clear all
512
     * notifications if namespace is not provided
513
     *
514
     * @param null $namespace
515
     * @return bool
516
     */
517 3
    public function clear($namespace = null)
518
    {
519 3
        $this->getNotificationsFromContainer();
520
521 3
        if ($namespace) {
522 2
            if (isset($this->notifications[$namespace])) {
523 1
                unset($this->notifications[$namespace]);
524 1
                return true;
525
            }
526
527 1
            return false;
528
        }
529
530 1
        foreach ($this->notifications as $nm => $type) {
531 1
            unset($this->notifications[$nm]);
532 1
        }
533
534 1
        return true;
535
    }
536
}