Passed
Pull Request — master (#29)
by Sébastien
03:40
created

Message::allowCompression()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Puzzle\AMQP\Messages;
4
5
use Psr\Log\InvalidArgumentException;
6
use Puzzle\AMQP\WritableMessage;
7
use Puzzle\AMQP\Messages\Bodies\NullBody;
8
use Puzzle\Pieces\ConvertibleToString;
9
10
class Message implements WritableMessage, ConvertibleToString
11
{
12
    use BodySetter;
13
    
14
    private
15
        $body,
16
        $canBeDroppedSilently,
17
        $allowCompression,
18
        $headers,
19
        $attributes;
20
21 31
    public function __construct($routingKey = '')
22 1
    {
23 31
        $this->body = new NullBody();
24
        
25 31
        $this->canBeDroppedSilently = true;
26 31
        $this->allowCompression = false;
27
        
28 31
        $this->headers = array();
29 31
        $this->initializeAttributes();
30
        
31 31
        $this->changeRoutingKey($routingKey);
32 31
    }
33
34 31
    public function changeRoutingKey($routingKey)
35
    {
36 31
        $this->setAttribute('routing_key', $routingKey);
37 31
    }
38
    
39 31
    private function initializeAttributes()
40
    {
41 31
        $this->attributes = array(
42 31
            'routing_key' => null,
43 31
            'content_type' => $this->getContentType(),
44 31
            'content_encoding' => 'utf8',
45
            'message_id' => function($timestamp) {
46 13
                return sha1($this->getRoutingKey() . $timestamp . $this->generateBodyId() . mt_rand());
47 31
            },
48 31
            'user_id' => null,
49 31
            'app_id' => null,
50 31
            'delivery_mode' => self::PERSISTENT,
51 31
            'priority' => null,
52
            'timestamp' => function($timestamp) {
53 14
                return $timestamp;
54 31
            },
55 31
            'expiration' => null,
56 31
            'type' => null,
57 31
            'reply_to' => null,
58 31
            'correlation_id' => null,
59
            'headers' => function($timestamp) {
60 15
                return $this->packHeaders($timestamp);
61 31
            },
62
        );
63 31
    }
64
    
65 13
    private function generateBodyId()
66
    {
67 13
        if($this->body instanceof Footprintable)
68 13
        {
69 2
            return $this->body->footprint();
70
        }
71
        
72 11
        return uniqid(true);
73
    }
74
    
75 1
    public function canBeDroppedSilently()
76
    {
77 1
        return $this->canBeDroppedSilently;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->canBeDroppedSilently; (boolean) is incompatible with the return type declared by the interface Puzzle\AMQP\WritableMessage::canBeDroppedSilently of type integer.

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...
78
    }
79
    
80 1
    public function disallowSilentDropping()
81
    {
82 1
        $this->canBeDroppedSilently = false;
83
        
84 1
        return $this;
85
    }
86
87 31
    public function getContentType()
88
    {
89 31
        return $this->body->getContentType();
90
    }
91
92 26
    public function getRoutingKey()
93
    {
94 26
        return $this->getAttribute('routing_key');
95
    }
96
97 4
    public function getBodyInTransportFormat()
98
    {
99 4
        return $this->body->asTransported();
100
    }
101
102 8
    public function setBody(Body $body)
103
    {
104 8
        $this->body = $body;
105 8
        $this->updateContentType();
106
        
107 8
        return $this;
108
    }
109
    
110 17
    private function updateContentType()
111
    {
112 17
        $this->attributes['content_type'] = $this->body->getContentType();
113 17
    }
114
115 19
    public function addHeader($headerName, $value)
116
    {
117 19
        $this->headers[$headerName] = $value;
118
119 19
        return $this;
120
    }
121
122 5
    public function addHeaders(array $headers)
123
    {
124 5
        foreach($headers as $name => $value)
125
        {
126 5
            $this->addHeader($name, $value);
127 5
        }
128
129 5
        return $this;
130
    }
131
132 1
    public function setAuthor($author)
133
    {
134 1
        $this->addHeader('author', $author);
135
136 1
        return $this;
137
    }
138
139 15
    public function packAttributes($timestamp = false)
140
    {
141 15
        $this->updateContentType();
142
        
143 15
        if($timestamp === false)
144 15
        {
145 13
            $timestamp = (new \DateTime("now"))->getTimestamp();
146 13
        }
147
148 15
        return array_map(function($value) use($timestamp) {
149
150 15
            if($value instanceof \Closure)
151 15
            {
152 15
                $value = $value($timestamp);
153 15
            }
154
155 15
            return $value;
156
157 15
        }, $this->attributes);
158
    }
159
160 15
    private function packHeaders($timestamp)
161
    {
162 15
        $this->headers['message_datetime'] = date('Y-m-d H:i:s', $timestamp);
163
164 15
        return $this->headers;
165
    }
166
167 31
    public function setAttribute($attributeName, $value)
168
    {
169 31
        if($attributeName !== 'headers')
170 31
        {
171 31
            if(array_key_exists($attributeName, $this->attributes))
172 31
            {
173 31
                $this->attributes[$attributeName] = $value;
174 31
            }
175 31
        }
176
177 31
        return $this;
178
    }
179
180 8
    public function getHeaders()
181
    {
182 8
        $attributes = $this->packAttributes();
183
184 8
        return $attributes['headers'];
185
    }
186
187 28
    public function getAttribute($attributeName)
188
    {
189 28
        if(array_key_exists($attributeName, $this->attributes))
190 28
        {
191 27
            return $this->attributes[$attributeName];
192
        }
193
194 1
        throw new InvalidArgumentException(sprintf('Property "%s" is unknown or is not a message property', $attributeName));
195
    }
196
197 1
    public function __toString()
198
    {
199 1
        return json_encode(array(
200 1
            'routing_key' => $this->getRoutingKey(),
201 1
            'body' => (string) $this->body,
202 1
            'attributes' => $this->attributes,
203 1
            'can be dropped silently' => $this->canBeDroppedSilently
204 1
        ));
205
    }
206
207 1
    public function setExpiration($expirationInSeconds)
208
    {
209 1
        $ttlInMs = 1000 * (int) $expirationInSeconds;
210
211 1
        $this->setAttribute('expiration', (string) $ttlInMs);
212
213 1
        return $this;
214
    }
215
    
216 4
    public function isCompressionAllowed()
217
    {
218 4
        return $this->allowCompression;
219
    }
220
    
221 3
    public function allowCompression()
222
    {
223 3
        $this->allowCompression = true;
224
        
225 3
        return $this;
226
    }
227
}
228