Completed
Push — develop ( 68eef9...892aaa )
by Tom
04:09
created

ClassifyRequest::sendData()   C

Complexity

Conditions 9
Paths 28

Size

Total Lines 60
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 9

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 60
ccs 22
cts 22
cp 1
rs 6.8358
cc 9
eloc 37
nc 28
nop 1
crap 9

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
namespace Bobbyshaw\WatsonVisualRecognition\Message;
4
5
use GuzzleHttp\Exception\ClientException;
6
use Bobbyshaw\WatsonVisualRecognition\Exceptions\AuthException;
7
use GuzzleHttp\Psr7\MultipartStream;
8
use GuzzleHttp\Psr7\Request;
9
10
/**
11
 * Class ClassifyRequest
12
 * @package Bobbyshaw\WatsonVisualRecognition\Message
13
 */
14
class ClassifyRequest extends AbstractRequest
15
{
16
    const CLASSIFY_PATH = 'classify/';
17
    const ALLOWED_FILE_TYPES = ['.gif', '.jpg', '.png', '.zip'];
18
19
    /**
20
     * Get parameters for classify request
21
     *
22
     * @return array
23
     *
24
     * ['images_file', 'classifier_ids']
25
     *
26
     */
27 3
    public function getData()
28
    {
29 3
        $data = parent::getData();
30
31 3
        $data['images_file'] = $this->getImagesFile();
32
33 3
        if ($classifierIds = $this->getClassifierIds()) {
34 3
            $data['classifier_ids'] = $classifierIds;
35
        }
36
37 3
        return $data;
1 ignored issue
show
Best Practice introduced by
The expression return $data; seems to be an array, but some of its elements' types (string[]) are incompatible with the return type of the parent method Bobbyshaw\WatsonVisualRe...bstractRequest::getData of type array<string,string>.

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 new Author('Johannes');
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return '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...
38
    }
39
40
    /**
41
     * Send Classify HTTP request
42
     *
43
     * @param array $data - array['images_file', 'classifier_ids']
44
     * @return ClassifyResponse
45
     * @throws AuthException
46
     * @throws \Exception
47
     */
48 2
    public function sendData($data)
49
    {
50 2
        if (!in_array(substr($data['images_file'], -4), static::ALLOWED_FILE_TYPES)) {
51
            throw new \InvalidArgumentException(
52
                'Image file needs to be one of the following types: ' . implode(', ', static::ALLOWED_FILE_TYPES)
53
            );
54
        }
55
56
        $params = [
57
            [
58 2
                'name' => 'images_file',
59 2
                'contents' => fopen($data['images_file'], 'r'),
60 2
                'filename' => $data['images_file']
61
            ]
62
        ];
63
64 2
        if (isset($data['classifier_ids'])) {
65 2
            if (is_array($data['classifier_ids'])) {
66 2
                $classifierIdParams = [];
67 2
                foreach ($data['classifier_ids'] as $id) {
68 2
                    $classifierIdParams[] = ['classifier_id' => $id];
69
                }
70
71 2
                $params[] = [
72 2
                    'name' => 'classifier_ids',
73 2
                    'contents' => json_encode(['classifiers' => $classifierIdParams])
74
                ];
75
            } else {
76
                throw new \InvalidArgumentException('Classifier IDs must be array');
77
            }
78
        }
79
80 2
        $multipartStream = new MultipartStream($params);
81
82 2
        $request = new Request(
83 2
            'POST',
84 2
            $this->getApiUrl(static::CLASSIFY_PATH) . '?' . http_build_query(['version' => $data['version']]),
85 2
            ['Authorization' => 'Basic ' . base64_encode($data['username'] . ':' . $data['password'])],
86
            $multipartStream
87
        );
88
89
        try {
90 2
            $response = $this->httpClient->send($request);
91
92 2
            if ($response->getStatusCode() != 200) {
93
                $error = $response->getStatusCode() . " Response Received: " . $response->getBody()->getContents();
94 2
                throw new \Exception($error, $response->getStatusCode());
95
            }
96
        } catch (ClientException $e) {
97
            if ($e->getCode() == 401) {
98
                throw new AuthException('Invalid credentials provided');
99
            } elseif ($e->getCode() == 415) {
100
                throw new \InvalidArgumentException('Unsupported image type');
101
            } else {
102
                throw $e;
103
            }
104
        }
105
106 2
        return $this->response = new ClassifyResponse($this, $response->getBody());
107
    }
108
}
109