Completed
Branch 2.x (c99d86)
by Julián
08:01
created

DefaultFactory::buildPushMessage()   B

Complexity

Conditions 6
Paths 32

Size

Total Lines 56
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 56
rs 8.7592
c 0
b 0
f 0
cc 6
eloc 38
nc 32
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * Unified push notification services abstraction (http://github.com/juliangut/tify).
5
 *
6
 * @license BSD-3-Clause
7
 * @link https://github.com/juliangut/tify
8
 * @author Julián Gutiérrez <[email protected]>
9
 */
10
11
namespace Jgut\Tify\Adapter\Apns;
12
13
use Jgut\Tify\Exception\AdapterException;
14
use Jgut\Tify\Message as NotificationMessage;
15
use Jgut\Tify\Notification;
16
use Jgut\Tify\Receiver\ApnsReceiver;
17
use ZendService\Apple\Apns\Client\AbstractClient;
18
use ZendService\Apple\Apns\Client\Feedback as FeedbackClient;
19
use ZendService\Apple\Apns\Client\Message as PushClient;
20
use ZendService\Apple\Apns\Message\Alert as ServiceMessageAlert;
21
use ZendService\Apple\Apns\Message as ServiceMessage;
22
23
/**
24
 * APNS default service factory.
25
 */
26
class DefaultFactory implements Factory
27
{
28
    /**
29
     * Alert parameters list.
30
     *
31
     * @var array
32
     */
33
    protected static $alertParams = [
34
        NotificationMessage::PARAMETER_TITLE,
35
        NotificationMessage::PARAMETER_BODY,
36
        NotificationMessage::PARAMETER_TITLE_LOC_KEY,
37
        NotificationMessage::PARAMETER_TITLE_LOC_ARGS,
38
        NotificationMessage::PARAMETER_BODY_LOC_KEY,
39
        NotificationMessage::PARAMETER_BODY_LOC_ARGS,
40
        NotificationMessage::PARAMETER_ACTION_LOC_KEY,
41
        NotificationMessage::PARAMETER_LAUNCH_IMAGE,
42
    ];
43
44
    /**
45
     * {@inheritdoc}
46
     *
47
     * @throws AdapterException
48
     *
49
     * @return PushClient
50
     */
51
    public function buildPushClient($certificate, $passPhrase = '', $sandbox = false)
52
    {
53
        return $this->buildClient(new PushClient, $certificate, $passPhrase, $sandbox);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->buildClien...$passPhrase, $sandbox); (ZendService\Apple\Apns\Client\AbstractClient) is incompatible with the return type declared by the interface Jgut\Tify\Adapter\Apns\Factory::buildPushClient of type Jgut\Tify\Adapter\Apns\AbstractClient.

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...
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     *
59
     * @throws AdapterException
60
     *
61
     * @return FeedbackClient
62
     */
63
    public function buildFeedbackClient($certificate, $passPhrase = null, $sandbox = false)
64
    {
65
        return $this->buildClient(new FeedbackClient, $certificate, $passPhrase, $sandbox);
66
    }
67
68
    /**
69
     * Get opened client.
70
     *
71
     * @param AbstractClient $client
72
     * @param string         $certificate
73
     * @param string         $passPhrase
74
     * @param bool           $sandbox
75
     *
76
     * @throws AdapterException
77
     *
78
     * @return AbstractClient|PushClient|FeedbackClient
79
     *
80
     * @codeCoverageIgnore
81
     */
82
    protected function buildClient(AbstractClient $client, $certificate, $passPhrase = '', $sandbox = false)
83
    {
84
        try {
85
            $client->open(
86
                (bool) $sandbox ? AbstractClient::SANDBOX_URI : AbstractClient::PRODUCTION_URI,
87
                $certificate,
88
                $passPhrase
89
            );
90
        } catch (\Exception $exception) {
91
            throw new AdapterException($exception->getMessage(), $exception->getCode(), $exception);
92
        }
93
94
        return $client;
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     *
100
     * @throws \ZendService\Apple\Exception\RuntimeException
101
     */
102
    public function buildPushMessage(ApnsReceiver $receiver, Notification $notification)
103
    {
104
        $message = $notification->getMessage();
105
106
        $messageId = sha1(
107
            sprintf(
108
                '%s%s%s%s',
109
                $receiver->getToken(),
110
                $message->getParameter(NotificationMessage::PARAMETER_TITLE),
111
                $message->getParameter(NotificationMessage::PARAMETER_BODY),
112
                time()
113
            )
114
        );
115
        $badge = $notification->getParameter(Notification::PARAMETER_BADGE) === null
116
            ? null
117
            : (int) $notification->getParameter(Notification::PARAMETER_BADGE);
118
119
        $pushMessage = (new ServiceMessage)
120
            ->setId($messageId)
121
            ->setToken($receiver->getToken())
122
            ->setBadge($badge)
123
            ->setSound($notification->getParameter(Notification::PARAMETER_SOUND))
124
            ->setCategory($notification->getParameter(Notification::PARAMETER_CATEGORY))
125
            ->setCustom($message->getPayloadData());
126
127
        if ($notification->getParameter(Notification::PARAMETER_CONTENT_AVAILABLE) !== null) {
128
            $pushMessage->setContentAvailable(
129
                (int) $notification->getParameter(Notification::PARAMETER_CONTENT_AVAILABLE)
130
            );
131
        }
132
133
        if (is_array($notification->getParameter(Notification::PARAMETER_URL_ARGS))) {
134
            $pushMessage->setUrlArgs($notification->getParameter(Notification::PARAMETER_URL_ARGS));
135
        }
136
137
        if ($notification->getParameter(Notification::PARAMETER_TTL) !== null) {
138
            $expire = time() + (int) $notification->getParameter(Notification::PARAMETER_TTL);
139
140
            $pushMessage->setExpire($expire);
141
        }
142
143
        if ($this->shouldHaveAlert($message)) {
144
            $pushMessage->setAlert(new ServiceMessageAlert(
145
                $message->getParameter(NotificationMessage::PARAMETER_BODY),
146
                $message->getParameter(NotificationMessage::PARAMETER_ACTION_LOC_KEY),
147
                $message->getParameter(NotificationMessage::PARAMETER_BODY_LOC_KEY),
148
                $message->getParameter(NotificationMessage::PARAMETER_BODY_LOC_ARGS),
149
                $message->getParameter(NotificationMessage::PARAMETER_LAUNCH_IMAGE),
150
                $message->getParameter(NotificationMessage::PARAMETER_TITLE),
151
                $message->getParameter(NotificationMessage::PARAMETER_TITLE_LOC_KEY),
152
                $message->getParameter(NotificationMessage::PARAMETER_TITLE_LOC_ARGS)
153
            ));
154
        }
155
156
        return $pushMessage;
157
    }
158
159
    /**
160
     * Message should have alert dictionary.
161
     *
162
     * @param NotificationMessage $message
163
     *
164
     * @return bool
165
     */
166
    private function shouldHaveAlert(NotificationMessage $message)
167
    {
168
        $shouldHaveAlert = false;
169
170
        foreach (static::$alertParams as $parameter) {
171
            if ($message->hasParameter($parameter)) {
172
                $shouldHaveAlert = true;
173
174
                break;
175
            }
176
        }
177
178
        return $shouldHaveAlert;
179
    }
180
}
181