|
1
|
|
|
<?php namespace nyx\diagnostics\debug; |
|
2
|
|
|
|
|
3
|
|
|
// External dependencies |
|
4
|
|
|
use nyx\core\collections; |
|
5
|
|
|
|
|
6
|
|
|
/** |
|
7
|
|
|
* Trace |
|
8
|
|
|
* |
|
9
|
|
|
* Sequence for \Exception::getTrace() frames which get converted into diagnostic\Frame instances when passed |
|
10
|
|
|
* to the constructor. The collection *is* mutable - the frames are numerically indexed (per assumption, in the |
|
11
|
|
|
* order returned by getTrace(), but other uses are obviously possible). |
|
12
|
|
|
* |
|
13
|
|
|
* Please refer to {@see core\collections\Sequence} and the corresponding trait for details on which methods are |
|
14
|
|
|
* available for Collections. This class only overrides those which might directly inject elements into the Collection, |
|
15
|
|
|
* in order to ensure proper types. Some methods (eg. map, filter) will return new Trace instances with the results |
|
16
|
|
|
* of their calls, and ultimately the constructor of a Frame will take care of type checks and only use the data |
|
17
|
|
|
* it knows about. |
|
18
|
|
|
* |
|
19
|
|
|
* @package Nyx\Diagnostics\Debug |
|
20
|
|
|
* @version 0.1.0 |
|
21
|
|
|
* @author Michal Chojnacki <[email protected]> |
|
22
|
|
|
* @copyright 2012-2016 Nyx Dev Team |
|
23
|
|
|
* @link http://docs.muyo.io/nyx/diagnostics/debug.html |
|
24
|
|
|
*/ |
|
25
|
|
|
class Trace extends collections\Sequence |
|
26
|
|
|
{ |
|
27
|
|
|
/** |
|
28
|
|
|
* {@inheritDoc} |
|
29
|
|
|
*/ |
|
30
|
|
|
public function push($frame) : collections\interfaces\Sequence |
|
31
|
|
|
{ |
|
32
|
|
|
return parent::push($this->assertValueIsFrame($frame)); |
|
|
|
|
|
|
33
|
|
|
} |
|
34
|
|
|
|
|
35
|
|
|
/** |
|
36
|
|
|
* {@inheritDoc} |
|
37
|
|
|
*/ |
|
38
|
|
|
public function prepend($frame) : collections\interfaces\Sequence |
|
39
|
|
|
{ |
|
40
|
|
|
return parent::prepend($this->assertValueIsFrame($frame)); |
|
|
|
|
|
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* {@inheritDoc} |
|
45
|
|
|
*/ |
|
46
|
|
|
public function update(int $index, $frame) : collections\interfaces\Sequence |
|
47
|
|
|
{ |
|
48
|
|
|
return parent::update($index, $this->assertValueIsFrame($frame)); |
|
|
|
|
|
|
49
|
|
|
} |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* {@inheritDoc} |
|
53
|
|
|
*/ |
|
54
|
|
|
public function contains($item) : bool |
|
55
|
|
|
{ |
|
56
|
|
|
// Avoid some overhead on simple type mismatches. |
|
57
|
|
|
if (!$item instanceof Frame) { |
|
58
|
|
|
return false; |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
return parent::contains($item); |
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
/** |
|
65
|
|
|
* Attempts to convert the given value to a Frame instance (if it isn't one already) and returns it if possible. |
|
66
|
|
|
* |
|
67
|
|
|
* @param mixed $value The value to check. |
|
68
|
|
|
* @return Frame |
|
69
|
|
|
* @throws \InvalidArgumentException When the given value is not a frame and could not be converted to one. |
|
70
|
|
|
*/ |
|
71
|
|
|
protected function assertValueIsFrame($value) |
|
72
|
|
|
{ |
|
73
|
|
|
if ($value instanceof Frame) { |
|
74
|
|
|
return $value; |
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
|
|
if (is_array($value)) { |
|
78
|
|
|
return new Frame($value); |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
throw new \InvalidArgumentException('The given value is not a Frame instance and could not be converted to one.'); |
|
82
|
|
|
} |
|
83
|
|
|
} |
|
84
|
|
|
|
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:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.