Completed
Push — experimental/3.1 ( 558b03...8b00e4 )
by Ryo
27s
created

OwnerStoreController   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 350
Duplicated Lines 5.71 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 20
loc 350
ccs 0
cts 96
cp 0
rs 9.2
c 0
b 0
f 0
wmc 34
lcom 1
cbo 9

7 Methods

Rating   Name   Duplication   Size   Complexity  
D search() 7 82 14
B doConfirm() 0 29 2
C apiInstall() 0 46 9
B deleteConfirm() 0 24 2
B apiUninstall() 0 29 4
B getRequestApi() 0 26 1
A getResponseErrorMessage() 13 13 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
 * This file is part of EC-CUBE
4
 *
5
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
6
 *
7
 * http://www.lockon.co.jp/
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 */
23
24
25
namespace Eccube\Controller\Admin\Store;
26
27
use Doctrine\ORM\EntityManager;
28
use Doctrine\ORM\EntityManagerInterface;
29
use Eccube\Annotation\Inject;
30
use Eccube\Application;
31
use Eccube\Common\Constant;
32
use Eccube\Controller\AbstractController;
33
use Eccube\Entity\Plugin;
34
use Eccube\Repository\PluginRepository;
35
use Eccube\Service\PluginService;
36
use Eccube\Service\ComposerProcessService;
37
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
38
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
39
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
40
use Symfony\Component\HttpFoundation\RedirectResponse;
41
use Symfony\Component\HttpFoundation\Request;
42
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
43
44
/**
45
 * @Route(service=OwnerStoreController::class)
46
 */
47
class OwnerStoreController extends AbstractController
48
{
49
    /**
50
     * @Inject("config")
51
     * @var array
52
     */
53
    protected $appConfig;
54
55
    /**
56
     * @Inject(PluginRepository::class)
57
     * @var PluginRepository
58
     */
59
    protected $pluginRepository;
60
61
    /**
62
     * @Inject(PluginService::class)
63
     * @var PluginService
64
     */
65
    protected $pluginService;
66
67
    /**
68
     * @Inject(ComposerProcessService::class)
69
     * @var ComposerProcessService
70
     */
71
    protected $composerService;
72
73
    /**
74
     * @var EntityManager
75
     * @Inject("orm.em")
76
     */
77
    protected $em;
78
79
    /**
80
     * Owner's Store Plugin Installation Screen - Search function
81
     *
82
     * @Route("/{_admin}/store/plugin/search", name="admin_store_plugin_owners_search")
83
     * @Template("Store/plugin_search.twig")
84
     * @param Application $app
85
     * @param Request     $request
86
     * @return array
87
     */
88
    public function search(Application $app, Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
89
    {
90
        // Acquire downloadable plug-in information from owners store
91
        $success = 0;
92
        $items = array();
93
        $promotionItems = array();
94
        $message = '';
95
        // Owner's store communication
96
        $url = $this->appConfig['owners_store_url'].'?method=list';
97
        list($json, $info) = $this->getRequestApi($url, $app);
98
        if ($json === false) {
99
            $message = $this->getResponseErrorMessage($info);
100
        } else {
101
            $data = json_decode($json, true);
102
            if (isset($data['success'])) {
103
                $success = $data['success'];
104
                if ($success == '1') {
105
                    $items = array();
106
                    // Check plugin installed
107
                    $arrPluginInstalled = $this->pluginRepository->findAll();
108
                    // Update_status 1 : not install/purchased 、2 : Installed、 3 : Update、4 : paid purchase
109
                    foreach ($data['item'] as $item) {
110
                        // Not install/purchased
111
                        $item['update_status'] = 1;
112
                        /** @var Plugin $plugin */
113
                        foreach ($arrPluginInstalled as $plugin) {
114
                            if ($plugin->getSource() == $item['product_id']) {
115
                                // Need update
116
                                $item['update_status'] = 3;
117
                                if ($plugin->getVersion() == $item['version']) {
118
                                    // Installed
119
                                    $item['update_status'] = 2;
120
                                }
121
                            }
122
                        }
123
                        $items[] = $item;
124
                    }
125
126
                    // EC-CUBE version check
127
                    $arrDependency = [];
0 ignored issues
show
Unused Code introduced by
$arrDependency is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
128
                    foreach ($items as &$item) {
129
                        // Not applicable version
130
                        $item['version_check'] = 0;
131
                        if (in_array(Constant::VERSION, $item['eccube_version'])) {
132
                            // Match version
133
                            $item['version_check'] = 1;
134
                        }
135
                        if ($item['price'] != '0' && $item['purchased'] == '0') {
136
                            // Not purchased with paid items
137
                            $item['update_status'] = 4;
138
                        }
139
140
                        // Add plugin dependency
141
                        $item['depend'] = $this->pluginService->getRequirePluginName($items, $item);
142
                    }
143
                    unset($item);
144
145
                    // Promotion item
146
                    $i = 0;
147 View Code Duplication
                    foreach ($items as $item) {
148
                        if ($item['promotion'] == 1) {
149
                            $promotionItems[] = $item;
150
                            unset($items[$i]);
151
                        }
152
                        $i++;
153
                    }
154
                } else {
155
                    $message = $data['error_code'] . ' : ' . $data['error_message'];
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
156
                }
157
            } else {
158
                $success = 0;
159
                $message = "EC-CUBEオーナーズストアにエラーが発生しています。";
160
            }
161
        }
162
163
        return [
164
            'success' => $success,
165
            'items' => $items,
166
            'promotionItems' => $promotionItems,
167
            'message' => $message,
168
        ];
169
    }
170
171
    /**
172
     * Do confirm page
173
     *
174
     * @Route("/{_admin}/store/plugin/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_install_confirm")
175
     * @Template("Store/plugin_confirm.twig")
176
     * @param Application $app
177
     * @param Request     $request
178
     * @param string      $id
179
     * @return array
180
     */
181
    public function doConfirm(Application $app, Request $request, $id)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
182
    {
183
        // Owner's store communication
184
        $url = $this->appConfig['owners_store_url'].'?method=list';
185
        list($json, $info) = $this->getRequestApi($url, $app);
0 ignored issues
show
Unused Code introduced by
The assignment to $info is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
186
        $data = json_decode($json, true);
187
        $items = $data['item'];
188
189
        // Find plugin in api
190
        $index = array_search($id, array_column($items, 'product_id'));
191
        if ($index === false) {
192
            throw new NotFoundHttpException();
193
        }
194
195
        $pluginCode = $items[$index]['product_code'];
196
197
        $plugin = $this->pluginService->buildInfo($items, $pluginCode);
198
199
        // Prevent infinity loop: A -> B -> A.
200
        $arrDependency[] = $plugin;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$arrDependency was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arrDependency = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
201
        $arrDependency = $this->pluginService->getDependency($items, $plugin, $arrDependency);
0 ignored issues
show
Bug introduced by
It seems like $plugin defined by $this->pluginService->bu...fo($items, $pluginCode) on line 197 can also be of type null; however, Eccube\Service\PluginService::getDependency() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
202
        // Unset first param
203
        unset($arrDependency[0]);
204
205
        return [
206
            'item' => $plugin,
207
            'arrDependency' => $arrDependency,
208
        ];
209
    }
210
211
    /**
212
     * Api Install plugin by composer connect with package repo
213
     *
214
     * @Route("/{_admin}/store/plugin/api/{pluginCode}/{eccubeVersion}/{version}" , name="admin_store_plugin_api_install")
215
     *
216
     * @param Application $app
217
     * @param Request     $request
218
     * @param string      $pluginCode
219
     * @param string      $eccubeVersion
220
     * @param string      $version
221
     * @return RedirectResponse
222
     */
223
    public function apiInstall(Application $app, Request $request, $pluginCode, $eccubeVersion, $version)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
224
    {
225
        // Check plugin code
226
        $url = $this->appConfig['owners_store_url'].'?eccube_version='.$eccubeVersion.'&plugin_code='.$pluginCode.'&version='.$version;
227
        list($json, $info) = $this->getRequestApi($url, $app);
0 ignored issues
show
Unused Code introduced by
The assignment to $info is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
228
        $existFlg = false;
229
        $data = json_decode($json, true);
230
        if ($data && isset($data['success'])) {
231
            $success = $data['success'];
232
            if ($success == '1') {
233
                foreach ($data['item'] as $item) {
234
                    if ($item['product_code'] == $pluginCode) {
235
                        $existFlg = true;
236
                        break;
237
                    }
238
                }
239
            }
240
        }
241
        if ($existFlg === false) {
242
            $app->log(sprintf('%s plugin not found!', $pluginCode));
243
            $app->addError('admin.plugin.not.found', 'admin');
244
245
            return $app->redirect($app->url('admin_store_plugin_owners_search'));
246
        }
247
248
        /**
249
         * Mysql lock in transaction
250
         * @link https://dev.mysql.com/doc/refman/5.7/en/lock-tables.html
251
         * @var EntityManagerInterface $em
252
         */
253
        $em = $this->em;
254
        if ($em->getConnection()->isTransactionActive()) {
255
            $em->getConnection()->commit();
256
            $em->getConnection()->beginTransaction();
257
        }
258
259
        $return = $this->composerService->execRequire($pluginCode);
260
        if ($return) {
261
            $app->addSuccess('admin.plugin.install.complete', 'admin');
262
263
            return $app->redirect($app->url('admin_store_plugin'));
264
        }
265
        $app->addError('admin.plugin.install.fail', 'admin');
266
267
        return $app->redirect($app->url('admin_store_plugin_owners_search'));
268
    }
269
270
    /**
271
     * Do confirm page
272
     *
273
     * @Route("/{_admin}/store/plugin/delete/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_delete_confirm")
274
     * @Template("Store/plugin_confirm_uninstall.twig")
275
     * @param Application $app
276
     * @param Plugin      $Plugin
277
     * @return array
278
     */
279
    public function deleteConfirm(Application $app, Plugin $Plugin)
280
    {
281
        // Owner's store communication
282
        $url = $this->appConfig['owners_store_url'].'?method=list';
283
        list($json, $info) = $this->getRequestApi($url, $app);
0 ignored issues
show
Unused Code introduced by
The assignment to $info is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
284
        $data = json_decode($json, true);
285
        $items = $data['item'];
286
287
        // Check plugin in api
288
        $pluginSource = $Plugin->getSource();
289
        $index = array_search($pluginSource, array_column($items, 'product_id'));
290
        if ($index === false) {
291
            throw new NotFoundHttpException();
292
        }
293
294
        // Build info
295
        $pluginCode = $Plugin->getCode();
296
        $plugin = $this->pluginService->buildInfo($items, $pluginCode);
297
        $plugin['id'] = $Plugin->getId();
298
299
        return [
300
            'item' => $plugin,
301
        ];
302
    }
303
304
    /**
305
     * New ways to remove plugin: using composer command
306
     *
307
     * @Method("DELETE")
308
     * @Route("/{_admin}/store/plugin/api/{id}/uninstall", requirements={"id" = "\d+"}, name="admin_store_plugin_api_uninstall")
309
     * @param Application $app
310
     * @param Plugin      $Plugin
311
     * @return RedirectResponse
312
     */
313
    public function apiUninstall(Application $app, Plugin $Plugin)
314
    {
315
        $this->isTokenValid($app);
316
317
        if ($Plugin->getEnable() == Constant::ENABLED) {
318
            $this->pluginService->disable($Plugin);
319
        }
320
        $pluginCode = $Plugin->getCode();
321
322
        /**
323
         * Mysql lock in transaction
324
         * @link https://dev.mysql.com/doc/refman/5.7/en/lock-tables.html
325
         * @var EntityManagerInterface $em
326
         */
327
        $em = $this->em;
328
        if ($em->getConnection()->isTransactionActive()) {
329
            $em->getConnection()->commit();
330
            $em->getConnection()->beginTransaction();
331
        }
332
333
        $return = $this->composerService->execRemove($pluginCode);
334
        if ($return) {
335
            $app->addSuccess('admin.plugin.uninstall.complete', 'admin');
336
        } else {
337
            $app->addError('admin.plugin.uninstall.error', 'admin');
338
        }
339
340
        return $app->redirect($app->url('admin_store_plugin'));
341
    }
342
343
    /**
344
     * API request processing
345
     *
346
     * @param string  $url
347
     * @param Application $app
348
     * @return array
349
     */
350
    private function getRequestApi($url, $app)
351
    {
352
        $curl = curl_init($url);
353
354
        // Option array
355
        $options = array(
356
            // HEADER
357
            CURLOPT_HTTPGET => true,
358
            CURLOPT_SSL_VERIFYPEER => false,
359
            CURLOPT_RETURNTRANSFER => true,
360
            CURLOPT_FAILONERROR => true,
361
            CURLOPT_CAINFO => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(),
362
        );
363
364
        // Set option value
365
        curl_setopt_array($curl, $options);
366
        $result = curl_exec($curl);
367
        $info = curl_getinfo($curl);
368
        $message = curl_error($curl);
369
        $info['message'] = $message;
370
        curl_close($curl);
371
372
        $app->log('http get_info', $info);
373
374
        return array($result, $info);
375
    }
376
377
    /**
378
     * Get message
379
     *
380
     * @param $info
381
     * @return string
382
     */
383 View Code Duplication
    private function getResponseErrorMessage($info)
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...
384
    {
385
        if (!empty($info)) {
386
            $statusCode = $info['http_code'];
387
            $message = $info['message'];
388
389
            $message = $statusCode.' : '.$message;
390
        } else {
391
            $message = "タイムアウトエラーまたはURLの指定に誤りがあります。";
392
        }
393
394
        return $message;
395
    }
396
}
397