Material   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 262
Duplicated Lines 3.82 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 10
loc 262
rs 10
c 0
b 0
f 0
wmc 24
lcom 1
cbo 5

13 Methods

Rating   Name   Duplication   Size   Complexity  
A uploadImage() 0 4 1
A uploadVoice() 0 4 1
A uploadFile() 0 4 1
A uploadVideo() 0 12 1
A uploadArticle() 0 19 4
A updateArticle() 0 10 3
A uploadArticleImage() 0 4 1
A get() 0 21 4
A delete() 0 4 1
A lists() 10 10 1
A stats() 0 4 1
A uploadMedia() 0 10 3
A getAPIByType() 0 12 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace EntWeChat\Material;
4
5
use EntWeChat\Core\AbstractAPI;
6
use EntWeChat\Core\Exceptions\InvalidArgumentException;
7
use EntWeChat\Message\Article;
8
9
/**
10
 * Class Material.
11
 */
12
class Material extends AbstractAPI
13
{
14
    /**
15
     * Allow media type.
16
     *
17
     * @var array
18
     */
19
    protected $allowTypes = ['image', 'voice', 'video', 'file', 'news_image'];
20
21
    const API_GET = 'https://qyapi.weixin.qq.com/cgi-bin/material/get';
22
    const API_UPLOAD = 'https://qyapi.weixin.qq.com/cgi-bin/material/add_material';
23
    const API_DELETE = 'https://qyapi.weixin.qq.com/cgi-bin/material/del';
24
    const API_STATS = 'https://qyapi.weixin.qq.com/cgi-bin/material/get_count';
25
    const API_LISTS = 'https://qyapi.weixin.qq.com/cgi-bin/material/batchget';
26
    const API_NEWS_UPLOAD = 'https://qyapi.weixin.qq.com/cgi-bin/material/add_mpnews';
27
    const API_NEWS_UPDATE = 'https://qyapi.weixin.qq.com/cgi-bin/material/update_mpnews';
28
    const API_NEWS_IMAGE_UPLOAD = 'https://qyapi.weixin.qq.com/cgi-bin/media/uploadimg';
29
30
    /**
31
     * Upload image.
32
     *
33
     * @param string $path
34
     *
35
     * @return string
36
     */
37
    public function uploadImage($path)
38
    {
39
        return $this->uploadMedia('image', $path);
40
    }
41
42
    /**
43
     * Upload voice.
44
     *
45
     * @param string $path
46
     *
47
     * @return string
48
     */
49
    public function uploadVoice($path)
50
    {
51
        return $this->uploadMedia('voice', $path);
52
    }
53
54
    /**
55
     * Upload file.
56
     *
57
     * @param string $path
58
     *
59
     * @return string
60
     */
61
    public function uploadFile($path)
62
    {
63
        return $this->uploadMedia('file', $path);
64
    }
65
66
    /**
67
     * Upload video.
68
     *
69
     * @param string $path
70
     * @param string $title
71
     * @param string $description
72
     *
73
     * @return string
74
     */
75
    public function uploadVideo($path, $title, $description)
76
    {
77
        $params = [
78
            'description' => json_encode(
79
                [
80
                    'title'        => $title,
81
                    'introduction' => $description,
82
                ], JSON_UNESCAPED_UNICODE),
83
        ];
84
85
        return $this->uploadMedia('video', $path, $params);
86
    }
87
88
    /**
89
     * Upload articles.
90
     *
91
     * @param array|Article $articles
92
     *
93
     * @return string
94
     */
95
    public function uploadArticle($articles)
96
    {
97
        if (!empty($articles['title']) || $articles instanceof Article) {
98
            $articles = [$articles];
99
        }
100
101
        $params = ['articles' => array_map(function ($article) {
102
            if ($article instanceof Article) {
103
                return $article->only([
104
                    'title', 'thumb_media_id', 'author', 'digest',
105
                    'show_cover_pic', 'content', 'content_source_url',
106
                ]);
107
            }
108
109
            return $article;
110
        }, $articles)];
111
112
        return $this->parseJSON('json', [self::API_NEWS_UPLOAD, $params]);
113
    }
114
115
    /**
116
     * Update article.
117
     *
118
     * @param string $mediaId
119
     * @param array  $article
120
     * @param int    $index
121
     *
122
     * @return bool
123
     */
124
    public function updateArticle($mediaId, $article, $index = 0)
125
    {
126
        $params = [
127
            'media_id' => $mediaId,
128
            'index'    => $index,
129
            'articles' => isset($article['title']) ? $article : (isset($article[$index]) ? $article[$index] : []),
130
        ];
131
132
        return $this->parseJSON('json', [self::API_NEWS_UPDATE, $params]);
133
    }
134
135
    /**
136
     * Upload image for article.
137
     *
138
     * @param string $path
139
     *
140
     * @return string
141
     */
142
    public function uploadArticleImage($path)
143
    {
144
        return $this->uploadMedia('news_image', $path);
145
    }
146
147
    /**
148
     * Fetch material.
149
     *
150
     * @param string $mediaId
151
     *
152
     * @return mixed
153
     */
154
    public function get($mediaId)
155
    {
156
        $response = $this->getHttp()->json(self::API_GET, ['media_id' => $mediaId]);
157
158
        foreach ($response->getHeader('Content-Type') as $mime) {
159
            if (preg_match('/(image|video|audio)/i', $mime)) {
160
                return $response->getBody();
161
            }
162
        }
163
164
        $json = $this->getHttp()->parseJSON($response);
165
166
        // XXX: 微信开发这帮混蛋,尼玛文件二进制输出不带header,简直日了!!!
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
167
        if (!$json) {
168
            return $response->getBody();
169
        }
170
171
        $this->checkAndThrow($json);
172
173
        return $json;
174
    }
175
176
    /**
177
     * Delete material by media ID.
178
     *
179
     * @param string $mediaId
180
     *
181
     * @return bool
182
     */
183
    public function delete($mediaId)
184
    {
185
        return $this->parseJSON('json', [self::API_DELETE, ['media_id' => $mediaId]]);
186
    }
187
188
    /**
189
     * List materials.
190
     *
191
     * example:
192
     *
193
     * {
194
     *   "total_count": TOTAL_COUNT,
195
     *   "item_count": ITEM_COUNT,
196
     *   "item": [{
197
     *             "media_id": MEDIA_ID,
198
     *             "name": NAME,
199
     *             "update_time": UPDATE_TIME
200
     *         },
201
     *         // more...
202
     *   ]
203
     * }
204
     *
205
     * @param string $type
206
     * @param int    $offset
207
     * @param int    $count
208
     *
209
     * @return array
210
     */
211 View Code Duplication
    public function lists($type, $offset = 0, $count = 50)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
212
    {
213
        $params = [
214
            'type'   => $type,
215
            'offset' => intval($offset),
216
            'count'  => min(50, $count),
217
        ];
218
219
        return $this->parseJSON('json', [self::API_LISTS, $params]);
220
    }
221
222
    /**
223
     * Get stats of materials.
224
     *
225
     * @return array
226
     */
227
    public function stats()
228
    {
229
        return $this->parseJSON('get', [self::API_STATS]);
230
    }
231
232
    /**
233
     * Upload material.
234
     *
235
     * @param string $type
236
     * @param string $path
237
     * @param array  $form
238
     *
239
     * @throws InvalidArgumentException
240
     *
241
     * @return string
242
     */
243
    protected function uploadMedia($type, $path, array $form = [])
244
    {
245
        if (!file_exists($path) || !is_readable($path)) {
246
            throw new InvalidArgumentException("File does not exist, or the file is unreadable: '$path'");
247
        }
248
249
        $form['type'] = $type;
250
251
        return $this->parseJSON('upload', [$this->getAPIByType($type), ['media' => $path], $form]);
252
    }
253
254
    /**
255
     * Get API by type.
256
     *
257
     * @param string $type
258
     *
259
     * @return string
260
     */
261
    public function getAPIByType($type)
262
    {
263
        switch ($type) {
264
            case 'news_image':
265
                $api = self::API_NEWS_IMAGE_UPLOAD;
266
                break;
267
            default:
268
                $api = self::API_UPLOAD;
269
        }
270
271
        return $api;
272
    }
273
}
274