Failed Conditions
Pull Request — experimental/3.1 (#2653)
by
unknown
20:21
created

OwnerStoreController::deleteConfirm()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 41
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 24
nc 4
nop 2
dl 0
loc 41
ccs 0
cts 0
cp 0
crap 20
rs 8.5806
c 0
b 0
f 0
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
namespace Eccube\Controller\Admin\Store;
24
25
use Doctrine\ORM\EntityManager;
26
use Eccube\Annotation\Inject;
27
use Eccube\Application;
28
use Eccube\Common\Constant;
29
use Eccube\Controller\AbstractController;
30
use Eccube\Entity\Plugin;
31
use Eccube\Repository\PluginRepository;
32
use Eccube\Service\Composer\ComposerServiceInterface;
33
use Eccube\Service\PluginService;
34
use Eccube\Service\SystemService;
35
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
36
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
37
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
38
use Symfony\Component\HttpFoundation\RedirectResponse;
39
use Symfony\Component\HttpFoundation\Request;
40
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
41
42
/**
43
 * @Route(service=OwnerStoreController::class)
44
 */
45
class OwnerStoreController extends AbstractController
46
{
47
    /**
48
     * @Inject("config")
49
     * @var array
50
     */
51
    protected $appConfig;
52
53
    /**
54
     * @Inject(PluginRepository::class)
55
     * @var PluginRepository
56
     */
57
    protected $pluginRepository;
58
59
    /**
60
     * @Inject(PluginService::class)
61
     * @var PluginService
62
     */
63
    protected $pluginService;
64
65
    /**
66
     * @Inject("eccube.service.composer")
67
     * @var ComposerServiceInterface
68
     */
69
    protected $composerService;
70
71
    /**
72
     * @var EntityManager
73
     * @Inject("orm.em")
74
     */
75
    protected $em;
76
77
    /**
78
     * @Inject(SystemService::class)
79
     * @var SystemService
80
     */
81
    protected $systemService;
82
83
    private static $vendorName = 'ec-cube';
84
85
    /**
86
     * Owner's Store Plugin Installation Screen - Search function
87
     *
88
     * @Route("/{_admin}/store/plugin/search", name="admin_store_plugin_owners_search")
89
     * @Template("Store/plugin_search.twig")
90
     * @param Application $app
91
     * @param Request     $request
92
     * @return array
93
     */
94
    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...
95
    {
96
        // Acquire downloadable plug-in information from owners store
97
        $success = 0;
98
        $items = array();
99
        $promotionItems = array();
100
        $message = '';
101
        // Owner's store communication
102
        $url = $this->appConfig['package_repo_url'].'/search/packages.json';
103
        list($json, $info) = $this->getRequestApi($url, $app);
104
        if ($json === false) {
105
            $message = $this->getResponseErrorMessage($info);
106
        } else {
107
            $data = json_decode($json, true);
108
            if (isset($data['success'])) {
109
                $success = $data['success'];
110
                if ($success == '1') {
111
                    $items = array();
112
                    // Check plugin installed
113
                    $arrPluginInstalled = $this->pluginRepository->findAll();
114
                    // Update_status 1 : not install/purchased 、2 : Installed、 3 : Update、4 : paid purchase
115
                    foreach ($data['item'] as $item) {
116
                        // Not install/purchased
117
                        $item['update_status'] = 1;
118
                        /** @var Plugin $plugin */
119
                        foreach ($arrPluginInstalled as $plugin) {
120
                            if ($plugin->getSource() == $item['product_id']) {
121
                                // Need update
122
                                $item['update_status'] = 3;
123
                                if ($plugin->getVersion() == $item['version']) {
124
                                    // Installed
125
                                    $item['update_status'] = 2;
126
                                }
127
                            }
128
                        }
129
                        $items[] = $item;
130
                    }
131
132
                    // EC-CUBE version check
133
                    $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...
134
                    foreach ($items as &$item) {
135
                        // Not applicable version
136
                        $item['version_check'] = 0;
137
                        if (in_array(Constant::VERSION, $item['eccube_version'])) {
138
                            // Match version
139
                            $item['version_check'] = 1;
140
                        }
141
                        if ($item['price'] != '0' && $item['purchased'] == '0') {
142
                            // Not purchased with paid items
143
                            $item['update_status'] = 4;
144
                        }
145
146
                        // Add plugin dependency
147
                        $item['depend'] = $this->pluginService->getRequirePluginName($items, $item);
148
                    }
149
                    unset($item);
150
151
                    // Promotion item
152
                    $i = 0;
153 View Code Duplication
                    foreach ($items as $item) {
154
                        if ($item['promotion'] == 1) {
155
                            $promotionItems[] = $item;
156
                            unset($items[$i]);
157
                        }
158
                        $i++;
159
                    }
160
                } else {
161
                    $message = $data['error_code'].' : '.$data['error_message'];
162
                }
163
            } else {
164
                $success = 0;
165
                $message = "EC-CUBEオーナーズストアにエラーが発生しています。";
166
            }
167
        }
168
169
        return [
170
            'success' => $success,
171
            'items' => $items,
172
            'promotionItems' => $promotionItems,
173
            'message' => $message,
174
        ];
175
    }
176
177
    /**
178
     * Do confirm page
179
     *
180
     * @Route("/{_admin}/store/plugin/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_install_confirm")
181
     * @Template("Store/plugin_confirm.twig")
182
     * @param Application $app
183
     * @param Request     $request
184
     * @param string      $id
185
     * @return array
186
     */
187
    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...
188
    {
189
        // Owner's store communication
190
        $url = $this->appConfig['package_repo_url'].'/search/packages.json';
191
        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...
192
        $data = json_decode($json, true);
193
        $items = $data['item'];
194
195
        // Find plugin in api
196
        $index = array_search($id, array_column($items, 'product_id'));
197
        if ($index === false) {
198
            throw new NotFoundHttpException();
199
        }
200
201
        $pluginCode = $items[$index]['product_code'];
202
203
        $plugin = $this->pluginService->buildInfo($items, $pluginCode);
204
205
        // Prevent infinity loop: A -> B -> A.
206
        $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...
207
        $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 203 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...
208
        // Unset first param
209
        unset($arrDependency[0]);
210
211
        return [
212
            'item' => $plugin,
213
            'arrDependency' => $arrDependency,
214
        ];
215
    }
216
217
    /**
218
     * Api Install plugin by composer connect with package repo
219
     *
220
     * @Route("/{_admin}/store/plugin/api/{pluginCode}/{eccubeVersion}/{version}" , name="admin_store_plugin_api_install")
221
     *
222
     * @param Application $app
223
     * @param Request     $request
224
     * @param string      $pluginCode
225
     * @param string      $eccubeVersion
226
     * @param string      $version
227
     * @return RedirectResponse
228
     */
229
    public function apiInstall(Application $app, Request $request, $pluginCode, $eccubeVersion, $version)
230
    {
231
        // Check plugin code
232
        $url = $this->appConfig['package_repo_url'].'/search/packages.json'.'?eccube_version='.$eccubeVersion.'&plugin_code='.$pluginCode.'&version='.$version;
233
        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...
234
        $existFlg = false;
235
        $data = json_decode($json, true);
236
        if ($data && isset($data['success'])) {
237
            $success = $data['success'];
238
            if ($success == '1' && isset($data['item'])) {
239
                foreach ($data['item'] as $item) {
240
                    if ($item['product_code'] == $pluginCode) {
241
                        $existFlg = true;
242
                        break;
243
                    }
244
                }
245
            }
246
        }
247
        if ($existFlg === false) {
248
            $app->log(sprintf('%s plugin not found!', $pluginCode));
249
            $app->addError('admin.plugin.not.found', 'admin');
250
251
            return $app->redirect($app->url('admin_store_plugin_owners_search'));
252
        }
253
        $dependents = array();
254
        $items = $data['item'];
255
        $plugin = $this->pluginService->buildInfo($items, $pluginCode);
256
        $dependents[] = $plugin;
257
        $dependents = $this->pluginService->getDependency($items, $plugin, $dependents);
0 ignored issues
show
Bug introduced by
It seems like $plugin defined by $this->pluginService->bu...fo($items, $pluginCode) on line 255 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...
258
259
        // Unset first param
260
        unset($dependents[0]);
261
        $dependentModifier = [];
262
        $packageNames = '';
263
        if (!empty($dependents)) {
264
            foreach ($dependents as $item) {
265
                $packageNames .= self::$vendorName . '/' . $item['product_code'] . ' ';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
266
                $pluginItem = [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
267
                    "product_code" => $item['product_code'],
268
                    "version" => $item['version']
269
                ];
270
                array_push($dependentModifier, $pluginItem);
271
            }
272
        }
273
        $packageNames .= self::$vendorName . '/' . $pluginCode;
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
274
        $return = $this->composerService->execRequire($packageNames);
275
        if ($return) {
276
            $url = $this->appConfig['package_repo_url'] . '/collect';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
277
            // $composerMode = 1 is ComposerApi
278
            $composerMode = $this->appConfig['api_mode'];
279
            if ($this->composerService instanceof ComposerProcessService) {
280
                $composerMode = $this->appConfig['exec_mode'];
281
            }
282
            $data = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
283
                'code' => $pluginCode,
284
                'version' => $version,
285
                'core_version' => $eccubeVersion,
286
                'php_version' => phpversion(),
287
                'db_version' => $this->systemService->getDbversion(),
288
                'os' => php_uname('s') . ' ' . php_uname('r') . ' ' . php_uname('v'),
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
289
                'host' => $request->getHost(),
290
                'web_server' => $request->server->get("SERVER_SOFTWARE"),
291
                'composer_version' => $this->composerService->composerVersion(),
292
                'composer_execute_mode' => $composerMode,
293
                'dependents' => json_encode($dependentModifier)
294
            );
295
            $this->postRequestApi($url, $app, $data);
296
            $app->addSuccess('admin.plugin.install.complete', 'admin');
297
298
            return $app->redirect($app->url('admin_store_plugin'));
299
        }
300
        $app->addError('admin.plugin.install.fail', 'admin');
301
302
        return $app->redirect($app->url('admin_store_plugin_owners_search'));
303
    }
304
305
    /**
306
     * Do confirm page
307
     *
308
     * @Route("/{_admin}/store/plugin/delete/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_delete_confirm")
309
     * @Template("Store/plugin_confirm_uninstall.twig")
310
     * @param Application $app
311
     * @param Plugin      $Plugin
312
     * @return array|RedirectResponse
313
     */
314
    public function deleteConfirm(Application $app, Plugin $Plugin)
315
    {
316
        // Owner's store communication
317
        $url = $this->appConfig['package_repo_url'].'/search/packages.json';
318
        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...
319
        $data = json_decode($json, true);
320
        $items = $data['item'];
321
322
        // The plugin depends on it
323
        $pluginCode = $Plugin->getCode();
324
        $otherDepend = $this->pluginService->findDependentPlugin($pluginCode);
325
326
        if (!empty($otherDepend)) {
327
            $DependPlugin = $this->pluginRepository->findOneBy(['code' => $otherDepend[0]]);
328
            $dependName = $otherDepend[0];
329
            if ($DependPlugin) {
330
                $dependName = $DependPlugin->getName();
331
            }
332
333
            $message = $app->trans('admin.plugin.uninstall.depend', ['%name%' => $Plugin->getName(), '%depend_name%' => $dependName]);
334
            $app->addError($message, 'admin');
335
336
            return $app->redirect($app->url('admin_store_plugin'));
337
        }
338
339
        // Check plugin in api
340
        $pluginSource = $Plugin->getSource();
341
        $index = array_search($pluginSource, array_column($items, 'product_id'));
342
        if ($index === false) {
343
            throw new NotFoundHttpException();
344
        }
345
346
        // Build info
347
        $pluginCode = $Plugin->getCode();
348
        $plugin = $this->pluginService->buildInfo($items, $pluginCode);
349
        $plugin['id'] = $Plugin->getId();
350
351
        return [
352
            'item' => $plugin,
353
        ];
354
    }
355
356
    /**
357
     * New ways to remove plugin: using composer command
358
     *
359
     * @Method("DELETE")
360
     * @Route("/{_admin}/store/plugin/api/{id}/uninstall", requirements={"id" = "\d+"}, name="admin_store_plugin_api_uninstall")
361
     * @param Application $app
362
     * @param Plugin      $Plugin
363
     * @return RedirectResponse
364
     */
365
    public function apiUninstall(Application $app, Plugin $Plugin)
366
    {
367
        $this->isTokenValid($app);
368
369
        if ($Plugin->isEnable()) {
370
            $this->pluginService->disable($Plugin);
371
        }
372
        $pluginCode = $Plugin->getCode();
373
        $packageName = self::$vendorName.'/'.$pluginCode;
374
        $return = $this->composerService->execRemove($packageName);
375
        if ($return) {
376
            $app->addSuccess('admin.plugin.uninstall.complete', 'admin');
377
        } else {
378
            $app->addError('admin.plugin.uninstall.error', 'admin');
379
        }
380
381
        return $app->redirect($app->url('admin_store_plugin'));
382
    }
383
384
    /**
385
     * API request processing
386
     *
387
     * @param string  $url
388
     * @param Application $app
389
     * @return array
390
     */
391
    private function getRequestApi($url, $app)
392
    {
393
        $curl = curl_init($url);
394
395
        // Option array
396
        $options = array(
397
            // HEADER
398
            CURLOPT_HTTPGET => true,
399
            CURLOPT_SSL_VERIFYPEER => false,
400
            CURLOPT_RETURNTRANSFER => true,
401
            CURLOPT_FAILONERROR => true,
402
            CURLOPT_CAINFO => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(),
403
        );
404
405
        // Set option value
406
        curl_setopt_array($curl, $options);
407
        $result = curl_exec($curl);
408
        $info = curl_getinfo($curl);
409
        $message = curl_error($curl);
410
        $info['message'] = $message;
411
        curl_close($curl);
412
413
        $app->log('http get_info', $info);
414
415
        return array($result, $info);
416
    }
417
418
    /**
419
     * API post request processing
420
     *
421
     * @param string  $url
422
     * @param Application $app
423
     * @param array $data
424
     * @return array
425
     */
426
    private function postRequestApi($url, $app, $data)
427
    {
428
        $curl = curl_init($url);
429
        curl_setopt($curl, CURLOPT_URL, $url);
430
        curl_setopt($curl, CURLOPT_POST, 1);
431
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
432
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
433
        $result = curl_exec($curl);
434
        $info = curl_getinfo($curl);
435
        $message = curl_error($curl);
436
        $info['message'] = $message;
437
        curl_close($curl);
438
439
        $app->log('http post_info', $info);
440
        return array($result, $info);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
441
    }
442
443
    /**
444
     * Get message
445
     *
446
     * @param $info
447
     * @return string
448
     */
449 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...
450
    {
451
        if (!empty($info)) {
452
            $statusCode = $info['http_code'];
453
            $message = $info['message'];
454
455
            $message = $statusCode.' : '.$message;
456
        } else {
457
            $message = "タイムアウトエラーまたはURLの指定に誤りがあります。";
458
        }
459
460
        return $message;
461
    }
462
}
463