Failed Conditions
Push — experimental/3.1 ( d52b28...afea38 )
by chihiro
28s
created

OwnerStoreController::apiUninstall()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 4
nop 2
dl 0
loc 19
ccs 0
cts 0
cp 0
crap 12
rs 9.4285
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\ComposerApiService;
33
use Eccube\Service\PluginService;
34
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
35
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
36
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
37
use Symfony\Component\HttpFoundation\RedirectResponse;
38
use Symfony\Component\HttpFoundation\Request;
39
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
40
41
/**
42
 * @Route(service=OwnerStoreController::class)
43
 */
44
class OwnerStoreController extends AbstractController
45
{
46
    /**
47
     * @Inject("config")
48
     * @var array
49
     */
50
    protected $appConfig;
51
52
    /**
53
     * @Inject(PluginRepository::class)
54
     * @var PluginRepository
55
     */
56
    protected $pluginRepository;
57
58
    /**
59
     * @Inject(PluginService::class)
60
     * @var PluginService
61
     */
62
    protected $pluginService;
63
64
    /**
65
     * @Inject(ComposerApiService::class)
66
     * @var ComposerApiService
67
     */
68
    protected $composerService;
69
70
    /**
71
     * @var EntityManager
72
     * @Inject("orm.em")
73
     */
74
    protected $em;
75
76
    private static $vendorName = 'ec-cube';
77
78
    /**
79
     * Owner's Store Plugin Installation Screen - Search function
80
     *
81
     * @Route("/{_admin}/store/plugin/search", name="admin_store_plugin_owners_search")
82
     * @Template("Store/plugin_search.twig")
83
     * @param Application $app
84
     * @param Request     $request
85
     * @return array
86
     */
87
    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...
88
    {
89
        // Acquire downloadable plug-in information from owners store
90
        $success = 0;
91
        $items = array();
92
        $promotionItems = array();
93
        $message = '';
94
        // Owner's store communication
95
        $url = $this->appConfig['package_repo_url'].'/search/packages.json';
96
        list($json, $info) = $this->getRequestApi($url, $app);
97
        if ($json === false) {
98
            $message = $this->getResponseErrorMessage($info);
99
        } else {
100
            $data = json_decode($json, true);
101
            if (isset($data['success'])) {
102
                $success = $data['success'];
103
                if ($success == '1') {
104
                    $items = array();
105
                    // Check plugin installed
106
                    $arrPluginInstalled = $this->pluginRepository->findAll();
107
                    // Update_status 1 : not install/purchased 、2 : Installed、 3 : Update、4 : paid purchase
108
                    foreach ($data['item'] as $item) {
109
                        // Not install/purchased
110
                        $item['update_status'] = 1;
111
                        /** @var Plugin $plugin */
112
                        foreach ($arrPluginInstalled as $plugin) {
113
                            if ($plugin->getSource() == $item['product_id']) {
114
                                // Need update
115
                                $item['update_status'] = 3;
116
                                if ($plugin->getVersion() == $item['version']) {
117
                                    // Installed
118
                                    $item['update_status'] = 2;
119
                                }
120
                            }
121
                        }
122
                        $items[] = $item;
123
                    }
124
125
                    // EC-CUBE version check
126
                    $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...
127
                    foreach ($items as &$item) {
128
                        // Not applicable version
129
                        $item['version_check'] = 0;
130
                        if (in_array(Constant::VERSION, $item['eccube_version'])) {
131
                            // Match version
132
                            $item['version_check'] = 1;
133
                        }
134
                        if ($item['price'] != '0' && $item['purchased'] == '0') {
135
                            // Not purchased with paid items
136
                            $item['update_status'] = 4;
137
                        }
138
139
                        // Add plugin dependency
140
                        $item['depend'] = $this->pluginService->getRequirePluginName($items, $item);
141
                    }
142
                    unset($item);
143
144
                    // Promotion item
145
                    $i = 0;
146 View Code Duplication
                    foreach ($items as $item) {
147
                        if ($item['promotion'] == 1) {
148
                            $promotionItems[] = $item;
149
                            unset($items[$i]);
150
                        }
151
                        $i++;
152
                    }
153
                } else {
154
                    $message = $data['error_code'].' : '.$data['error_message'];
155
                }
156
            } else {
157
                $success = 0;
158
                $message = "EC-CUBEオーナーズストアにエラーが発生しています。";
159
            }
160
        }
161
162
        return [
163
            'success' => $success,
164
            'items' => $items,
165
            'promotionItems' => $promotionItems,
166
            'message' => $message,
167
        ];
168
    }
169
170
    /**
171
     * Do confirm page
172
     *
173
     * @Route("/{_admin}/store/plugin/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_install_confirm")
174
     * @Template("Store/plugin_confirm.twig")
175
     * @param Application $app
176
     * @param Request     $request
177
     * @param string      $id
178
     * @return array
179
     */
180
    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...
181
    {
182
        // Owner's store communication
183
        $url = $this->appConfig['package_repo_url'].'/search/packages.json';
184
        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...
185
        $data = json_decode($json, true);
186
        $items = $data['item'];
187
188
        // Find plugin in api
189
        $index = array_search($id, array_column($items, 'product_id'));
190
        if ($index === false) {
191
            throw new NotFoundHttpException();
192
        }
193
194
        $pluginCode = $items[$index]['product_code'];
195
196
        $plugin = $this->pluginService->buildInfo($items, $pluginCode);
197
198
        // Prevent infinity loop: A -> B -> A.
199
        $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...
200
        $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 196 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...
201
        // Unset first param
202
        unset($arrDependency[0]);
203
204
        return [
205
            'item' => $plugin,
206
            'arrDependency' => $arrDependency,
207
        ];
208
    }
209
210
    /**
211
     * Api Install plugin by composer connect with package repo
212
     *
213
     * @Route("/{_admin}/store/plugin/api/{pluginCode}/{eccubeVersion}/{version}" , name="admin_store_plugin_api_install")
214
     *
215
     * @param Application $app
216
     * @param Request     $request
217
     * @param string      $pluginCode
218
     * @param string      $eccubeVersion
219
     * @param string      $version
220
     * @return RedirectResponse
221
     */
222
    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...
223
    {
224
        // Check plugin code
225
        $url = $this->appConfig['package_repo_url'].'/search/packages.json'.'?eccube_version='.$eccubeVersion.'&plugin_code='.$pluginCode.'&version='.$version;
226
        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...
227
        $existFlg = false;
228
        $data = json_decode($json, true);
229
        if ($data && isset($data['success'])) {
230
            $success = $data['success'];
231
            if ($success == '1') {
232
                foreach ($data['item'] as $item) {
233
                    if ($item['product_code'] == $pluginCode) {
234
                        $existFlg = true;
235
                        break;
236
                    }
237
                }
238
            }
239
        }
240
        if ($existFlg === false) {
241
            $app->log(sprintf('%s plugin not found!', $pluginCode));
242
            $app->addError('admin.plugin.not.found', 'admin');
243
244
            return $app->redirect($app->url('admin_store_plugin_owners_search'));
245
        }
246
247
        $packageName = self::$vendorName.'/'.$pluginCode;
248
        $return = $this->composerService->execRequire($packageName);
249
        if ($return) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $return of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
250
            $app->addSuccess('admin.plugin.install.complete', 'admin');
251
252
            return $app->redirect($app->url('admin_store_plugin'));
253
        }
254
        $app->addError('admin.plugin.install.fail', 'admin');
255
256
        return $app->redirect($app->url('admin_store_plugin_owners_search'));
257
    }
258
259
    /**
260
     * Do confirm page
261
     *
262
     * @Route("/{_admin}/store/plugin/delete/{id}/confirm", requirements={"id" = "\d+"}, name="admin_store_plugin_delete_confirm")
263
     * @Template("Store/plugin_confirm_uninstall.twig")
264
     * @param Application $app
265
     * @param Plugin      $Plugin
266
     * @return array
267
     */
268
    public function deleteConfirm(Application $app, Plugin $Plugin)
269
    {
270
        // Owner's store communication
271
        $url = $this->appConfig['package_repo_url'].'/search/packages.json';
272
        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...
273
        $data = json_decode($json, true);
274
        $items = $data['item'];
275
276
        // Check plugin in api
277
        $pluginSource = $Plugin->getSource();
278
        $index = array_search($pluginSource, array_column($items, 'product_id'));
279
        if ($index === false) {
280
            throw new NotFoundHttpException();
281
        }
282
283
        // Build info
284
        $pluginCode = $Plugin->getCode();
285
        $plugin = $this->pluginService->buildInfo($items, $pluginCode);
286
        $plugin['id'] = $Plugin->getId();
287
288
        return [
289
            'item' => $plugin,
290
        ];
291
    }
292
293
    /**
294
     * New ways to remove plugin: using composer command
295
     *
296
     * @Method("DELETE")
297
     * @Route("/{_admin}/store/plugin/api/{id}/uninstall", requirements={"id" = "\d+"}, name="admin_store_plugin_api_uninstall")
298
     * @param Application $app
299
     * @param Plugin      $Plugin
300
     * @return RedirectResponse
301
     */
302
    public function apiUninstall(Application $app, Plugin $Plugin)
303
    {
304
        $this->isTokenValid($app);
305
306
        if ($Plugin->getEnable() == Constant::ENABLED) {
307
            $this->pluginService->disable($Plugin);
308
        }
309
        $pluginCode = $Plugin->getCode();
310
311
        $packageName = self::$vendorName.'/'.$pluginCode;
312
        $return = $this->composerService->execRemove($packageName);
313
        if ($return) {
314
            $app->addSuccess('admin.plugin.uninstall.complete', 'admin');
315
        } else {
316
            $app->addError('admin.plugin.uninstall.error', 'admin');
317
        }
318
319
        return $app->redirect($app->url('admin_store_plugin'));
320
    }
321
322
    /**
323
     * API request processing
324
     *
325
     * @param string  $url
326
     * @param Application $app
327
     * @return array
328
     */
329
    private function getRequestApi($url, $app)
330
    {
331
        $curl = curl_init($url);
332
333
        // Option array
334
        $options = array(
335
            // HEADER
336
            CURLOPT_HTTPGET => true,
337
            CURLOPT_SSL_VERIFYPEER => false,
338
            CURLOPT_RETURNTRANSFER => true,
339
            CURLOPT_FAILONERROR => true,
340
            CURLOPT_CAINFO => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(),
341
        );
342
343
        // Set option value
344
        curl_setopt_array($curl, $options);
345
        $result = curl_exec($curl);
346
        $info = curl_getinfo($curl);
347
        $message = curl_error($curl);
348
        $info['message'] = $message;
349
        curl_close($curl);
350
351
        $app->log('http get_info', $info);
352
353
        return array($result, $info);
354
    }
355
356
    /**
357
     * Get message
358
     *
359
     * @param $info
360
     * @return string
361
     */
362 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...
363
    {
364
        if (!empty($info)) {
365
            $statusCode = $info['http_code'];
366
            $message = $info['message'];
367
368
            $message = $statusCode.' : '.$message;
369
        } else {
370
            $message = "タイムアウトエラーまたはURLの指定に誤りがあります。";
371
        }
372
373
        return $message;
374
    }
375
}
376