Passed
Push — main ( d5ff59...b03a29 )
by Michiel
09:01
created

GrowlNotifyTask::setSticky()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
/**
4
 * Copyright (c) 2012-2013, Laurent Laville <[email protected]>.
5
 *
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 *     * Redistributions of source code must retain the above copyright
13
 *       notice, this list of conditions and the following disclaimer.
14
 *     * Redistributions in binary form must reproduce the above copyright
15
 *       notice, this list of conditions and the following disclaimer in the
16
 *       documentation and/or other materials provided with the distribution.
17
 *     * Neither the name of the authors nor the names of its contributors
18
 *       may be used to endorse or promote products derived from this software
19
 *       without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
 * POSSIBILITY OF SUCH DAMAGE.
32
 *
33
 * PHP version 5
34
 *
35
 * @category Tasks
36
 *
37
 * @author   Laurent Laville <[email protected]>
38
 * @license  http://www.opensource.org/licenses/bsd-license.php  BSD License
39
 *
40
 * @see     https://github.com/llaville/phing-GrowlNotifyTask
41
 */
42
43
namespace Phing\Task\Optional;
44
45
use Net_Growl;
46
use Net_Growl_Exception;
47
use Phing\Exception\BuildException;
48
use Phing\Project;
49
use Phing\Task;
50
51
/**
52
 * Growl notification task for Phing, the PHP build tool.
53
 *
54
 * PHP version 5
55
 *
56
 * @category Tasks
57
 *
58
 * @author   Laurent Laville <[email protected]>
59
 * @license  http://www.opensource.org/licenses/bsd-license.php  BSD License
60
 *
61
 * @see     https://github.com/llaville/phing-GrowlNotifyTask
62
 */
63
class GrowlNotifyTask extends Task
64
{
65
    protected $growl;
66
67
    protected $name;
68
    protected $sticky;
69
    protected $message;
70
    protected $title;
71
    protected $notification;
72
    protected $appicon;
73
    protected $host;
74
    protected $password;
75
    protected $priority;
76
    protected $protocol;
77
    protected $icon;
78
79
    /**
80
     * Initializes task with default options.
81
     *
82
     * @param Net_Growl $growl (optional) mock instance
83
     */
84 14
    public function __construct(Net_Growl $growl = null)
85
    {
86 14
        parent::__construct();
87 14
        $this->growl = $growl;
88
    }
89
90
    /**
91
     * The init method check if Net_Growl is available
92
     * (exists and can be loaded).
93
     *
94
     * @throws BuildException
95
     */
96 6
    public function init()
97
    {
98 6
        $autoloader = 'Net/Growl/Autoload.php';
99
100 6
        if (!$handle = @fopen($autoloader, 'r', true)) {
101
            throw new BuildException(
102
                'The Growl Notify task requires the pear/net_growl package.'
103
            );
104
        }
105
106 6
        fclose($handle);
107
108 6
        include_once $autoloader;
109
110 6
        $this->setTaskName('GrowlNotify');
111 6
        $this->setName();
112 6
        $this->setSticky(false);
113 6
        $this->setMessage();
114 6
        $this->setTitle();
115 6
        $this->setNotification();
116 6
        $this->setAppicon();
117 6
        $this->setHost();
118 6
        $this->setPassword();
119 6
        $this->setPriority();
120 6
        $this->setProtocol();
121 6
        $this->setIcon();
122
    }
123
124
    /**
125
     * Defines the name of the application sending the notification.
126
     *
127
     * @param string $name (optional) Name of the application
128
     *                     that appears in your Growl preferences
129
     *                     Default: "Growl for Phing"
130
     *
131
     * @throws BuildException
132
     */
133 6
    public function setName($name = '')
134
    {
135 6
        if ('' == $name) {
136 6
            $name = 'Growl for Phing';
137
        }
138
139 6
        if (!is_string($name)) {
0 ignored issues
show
introduced by
The condition is_string($name) is always true.
Loading history...
140
            throw new BuildException(
141
                '"name" attribute is invalid.' .
142
                ' Expect to be a string, actual is ' . gettype($name)
143
            );
144
        }
145
146 6
        $this->name = $name;
147
    }
148
149
    /**
150
     * Indicates if the notification should be sticky.
151
     *
152
     * @param bool $sticky (optional) Notification should be sticky
153
     */
154 7
    public function setSticky(bool $sticky = true)
155
    {
156 7
        $this->sticky = $sticky;
157
    }
158
159
    /**
160
     * The notification's text is required.
161
     * Use \n to specify a line break.
162
     *
163
     * @param string $message Notification's text
164
     *
165
     * @throws BuildException
166
     */
167 14
    public function setMessage($message = '')
168
    {
169 14
        if (!is_string($message)) {
0 ignored issues
show
introduced by
The condition is_string($message) is always true.
Loading history...
170
            throw new BuildException(
171
                '"message" attribute is invalid.' .
172
                ' Expect to be a string, actual is ' . gettype($message)
173
            );
174
        }
175
176 14
        $this->message = $message;
177
    }
178
179
    /**
180
     * The notification's title.
181
     * Use \n to specify a line break.
182
     *
183
     * @param string $title (optional) Notification's title
184
     *                      Default: GrowlNotify
185
     *
186
     * @throws BuildException
187
     */
188 7
    public function setTitle($title = '')
189
    {
190 7
        if ('' == $title) {
191 6
            $title = 'GrowlNotify';
192
        }
193
194 7
        if (!is_string($title)) {
0 ignored issues
show
introduced by
The condition is_string($title) is always true.
Loading history...
195
            throw new BuildException(
196
                '"title" attribute is invalid.' .
197
                ' Expect to be a string, actual is ' . gettype($title)
198
            );
199
        }
200
201 7
        $this->title = $title;
202
    }
203
204
    /**
205
     * The notification name/type.
206
     *
207
     * @param string $notification Name/type
208
     *                             Default: "General Notification"
209
     *
210
     * @throws BuildException
211
     */
212 7
    public function setNotification($notification = '')
213
    {
214 7
        if ('' == $notification) {
215 6
            $notification = 'General Notification';
216
        }
217
218 7
        if (!is_string($notification)) {
0 ignored issues
show
introduced by
The condition is_string($notification) is always true.
Loading history...
219
            throw new BuildException(
220
                '"notification" attribute is invalid.' .
221
                ' Expect to be a string, actual is ' . gettype($notification)
222
            );
223
        }
224
225 7
        $this->notification = $notification;
226
    }
227
228
    /**
229
     * The icon of the application being registered.
230
     *
231
     * Must be a valid file type (png, jpg, gif, ico).
232
     * Can be any of the following:
233
     *  - absolute url (http://domain/image.png)
234
     *  - absolute file path (c:\temp\image.png)
235
     *  - relative file path (.\folder\image.png) (relative file paths must start
236
     *    with a dot and are relative to GrowlNotify's phing task location
237
     *
238
     * @param string $icon Icon of the application
239
     *
240
     * @throws BuildException
241
     */
242 8
    public function setAppicon($icon = '')
243
    {
244 8
        if (!is_string($icon)) {
0 ignored issues
show
introduced by
The condition is_string($icon) is always true.
Loading history...
245
            throw new BuildException(
246
                '"appicon" attribute is invalid.' .
247
                ' Expect to be a string, actual is ' . gettype($icon)
248
            );
249
        }
250
251
        // relative location
252 8
        if (0 === strpos($icon, '..')) {
253 2
            $icon = realpath(__DIR__ . DIRECTORY_SEPARATOR . $icon);
254 6
        } elseif (0 === strpos($icon, '.')) {
255
            $icon = __DIR__ . substr($icon, 1);
256
        }
257
258 8
        $this->appicon = $icon;
259
    }
260
261
    /**
262
     * The host address to send the notification to.
263
     *
264
     * If any value other than 'localhost' or '127.0.0.1' is provided, the host
265
     * is considered a remote host and the "pass" attribute must also be provided.
266
     * Default: 127.0.0.1
267
     *
268
     * @param string $host Remote host name/ip
269
     *                     Default: 127.0.0.1
270
     *
271
     * @throws BuildException
272
     */
273 7
    public function setHost($host = '127.0.0.1')
274
    {
275 7
        if (!is_string($host)) {
0 ignored issues
show
introduced by
The condition is_string($host) is always true.
Loading history...
276
            throw new BuildException(
277
                '"host" attribute is invalid.' .
278
                ' Expect to be a string, actual is ' . gettype($host)
279
            );
280
        }
281
282 7
        $this->host = $host;
283
    }
284
285
    /**
286
     * The password required to send notifications.
287
     *
288
     * A password is required to send a request to a remote host. If host attribute
289
     * is specified and is any value other than 'localhost' or '127.0.0.1',
290
     * then "pass" attribute is also required.
291
     * Default: no password
292
     *
293
     * @param string $password Password to send request to a remote host
294
     *
295
     * @throws BuildException
296
     */
297 6
    public function setPassword($password = '')
298
    {
299 6
        if (!is_string($password)) {
0 ignored issues
show
introduced by
The condition is_string($password) is always true.
Loading history...
300
            throw new BuildException(
301
                '"password" attribute is invalid.' .
302
                ' Expect to be a string, actual is ' . gettype($password)
303
            );
304
        }
305
306 6
        $this->password = $password;
307
    }
308
309
    /**
310
     * The notification priority.
311
     *
312
     * Valid values are : low, moderate, normal, high, emergency
313
     * Default: normal
314
     *
315
     * @param string $priority Notification priority
316
     *                         Default: normal
317
     *
318
     * @throws BuildException
319
     */
320 7
    public function setPriority($priority = '')
321
    {
322 7
        if ('' == $priority) {
323 6
            $priority = 'normal';
324
        }
325
326 7
        switch ($priority) {
327 7
            case 'low':
328
                $priority = Net_Growl::PRIORITY_LOW;
329
330
                break;
331
332 7
            case 'moderate':
333
                $priority = Net_Growl::PRIORITY_MODERATE;
334
335
                break;
336
337 7
            case 'normal':
338 6
                $priority = Net_Growl::PRIORITY_NORMAL;
339
340 6
                break;
341
342 1
            case 'high':
343 1
                $priority = Net_Growl::PRIORITY_HIGH;
344
345 1
                break;
346
347
            case 'emergency':
348
                $priority = Net_Growl::PRIORITY_EMERGENCY;
349
350
                break;
351
352
            default:
353
                throw new BuildException(
354
                    '"priority" attribute is invalid.'
355
                );
356
        }
357
358 7
        $this->priority = $priority;
359
    }
360
361
    /**
362
     * The protocol (and port) to send the notification to.
363
     *
364
     * With TCP (GNTP) protocol, port is always 23053
365
     * With UDP protocol, port is always 9887
366
     * Default: 23053
367
     *
368
     * @param string $protocol Protocol to use to send request to remote host
369
     *                         Default: gntp
370
     *
371
     * @throws BuildException
372
     */
373 6
    public function setProtocol($protocol = '')
374
    {
375 6
        if ('' == $protocol) {
376 6
            $protocol = 'gntp';
377
        }
378
379 6
        switch ($protocol) {
380 6
            case 'udp':
381 6
            case 'gntp':
382 6
                break;
383
384
            default:
385
                throw new BuildException(
386
                    '"protocol" attribute is invalid.' .
387
                    ' Expect to be either udp or gntp.'
388
                );
389
        }
390
391 6
        $this->protocol = $protocol;
392
    }
393
394
    /**
395
     * The icon to show for the notification.
396
     *
397
     * Must be a valid file type (png, jpg, gif, ico).
398
     * Can be any of the following:
399
     *  - absolute url (http://domain/image.png)
400
     *  - absolute file path (c:\temp\image.png)
401
     *  - relative file path (.\folder\image.png) (relative file paths must start
402
     *    with a dot and are relative to GrowlNotify's phing task location
403
     *
404
     * @param string $icon Icon of the message
405
     *
406
     * @throws BuildException
407
     */
408 7
    public function setIcon($icon = '')
409
    {
410 7
        if (!is_string($icon)) {
0 ignored issues
show
introduced by
The condition is_string($icon) is always true.
Loading history...
411
            throw new BuildException(
412
                '"icon" attribute is invalid.' .
413
                ' Expect to be a string, actual is ' . gettype($icon)
414
            );
415
        }
416
417
        // relative location
418 7
        if (0 === strpos($icon, '..')) {
419 1
            $icon = realpath(__DIR__ . DIRECTORY_SEPARATOR . $icon);
420 6
        } elseif (0 === strpos($icon, '.')) {
421
            $icon = __DIR__ . substr($icon, 1);
422
        }
423
424 7
        $this->icon = $icon;
425
    }
426
427
    /**
428
     * The main entry point method.
429
     *
430
     * @throws BuildException
431
     */
432 14
    public function main()
433
    {
434 14
        if (empty($this->message)) {
435 1
            throw new BuildException(
436
                '"message" attribute cannot be empty'
437
            );
438
        }
439
440
        $notifications = [
441 13
            $this->notification,
442
        ];
443
        $options = [
444 13
            'host' => $this->host,
445 13
            'protocol' => $this->protocol,
446
        ];
447 13
        if (!empty($this->appicon)) {
448
            $options['AppIcon'] = $this->appicon;
449
        }
450
451
        try {
452 13
            if ($this->growl instanceof Net_Growl) {
453 8
                $growl = $this->growl;
454
            } else {
455 5
                $growl = Net_Growl::singleton(
456 5
                    $this->name,
457
                    $notifications,
458 5
                    $this->password,
459
                    $options
460
                );
461
            }
462 13
            $response = $growl->register();
463
464 13
            if ('gntp' == $this->protocol) {
465 5
                if ('OK' != $response->getStatus()) {
466
                    throw new BuildException(
467
                        'Growl Error ' . $response->getErrorCode() .
468
                        ' - ' . $response->getErrorDescription()
469
                    );
470
                }
471
            }
472 13
            $this->log(
473 13
                'Application ' . $this->name . ' registered',
474
                Project::MSG_VERBOSE
475
            );
476
477
            $logRequest = [
478 13
                'Application-Name' => $this->name,
479 13
                'Application-Icon' => $this->appicon,
480 13
                'Notification-Name' => $this->notification,
481 13
                'Notification-Title' => $this->title,
482 13
                'Notification-Text' => $this->message,
483 13
                'Notification-Priority' => $this->priority,
484 13
                'Notification-Icon' => $this->icon,
485 13
                'Notification-Sticky' => $this->sticky,
486
            ];
487 13
            foreach ($logRequest as $key => $value) {
488 13
                $this->log($key . ': ' . $value, Project::MSG_DEBUG);
489
            }
490
491
            $options = [
492 13
                'sticky' => $this->sticky,
493 13
                'priority' => $this->priority,
494 13
                'icon' => $this->icon,
495
            ];
496 13
            $response = $growl->publish(
497 13
                $this->notification,
498 13
                $this->title,
499 13
                $this->message,
500
                $options
0 ignored issues
show
Bug introduced by
$options of type array is incompatible with the type string expected by parameter $options of Net_Growl::publish(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

500
                /** @scrutinizer ignore-type */ $options
Loading history...
501
            );
502
503 13
            if ('gntp' == $this->protocol) {
504 5
                if ('OK' != $response->getStatus()) {
505
                    throw new BuildException(
506
                        'Growl Error ' . $response->getErrorCode() .
507
                        ' - ' . $response->getErrorDescription()
508
                    );
509
                }
510
            }
511 13
            $this->log('Notification was sent to remote host ' . $this->host);
512
        } catch (Net_Growl_Exception $e) {
513
            throw new BuildException(
514
                'Growl Exception : ' . $e->getMessage()
515
            );
516
        }
517
    }
518
}
519