These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of EC-CUBE |
||
5 | * |
||
6 | * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. |
||
7 | * |
||
8 | * http://www.ec-cube.co.jp/ |
||
9 | * |
||
10 | * For the full copyright and license information, please view the LICENSE |
||
11 | * file that was distributed with this source code. |
||
12 | */ |
||
13 | |||
14 | namespace Eccube\Controller\Admin\Product; |
||
15 | |||
16 | use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; |
||
17 | use Eccube\Common\Constant; |
||
18 | use Eccube\Controller\AbstractController; |
||
19 | use Eccube\Entity\BaseInfo; |
||
20 | use Eccube\Entity\ExportCsvRow; |
||
21 | use Eccube\Entity\Master\CsvType; |
||
22 | use Eccube\Entity\Master\ProductStatus; |
||
23 | use Eccube\Entity\Product; |
||
24 | use Eccube\Entity\ProductCategory; |
||
25 | use Eccube\Entity\ProductClass; |
||
26 | use Eccube\Entity\ProductImage; |
||
27 | use Eccube\Entity\ProductStock; |
||
28 | use Eccube\Entity\ProductTag; |
||
29 | use Eccube\Event\EccubeEvents; |
||
30 | use Eccube\Event\EventArgs; |
||
31 | use Eccube\Form\Type\Admin\ProductType; |
||
32 | use Eccube\Form\Type\Admin\SearchProductType; |
||
33 | use Eccube\Repository\BaseInfoRepository; |
||
34 | use Eccube\Repository\CategoryRepository; |
||
35 | use Eccube\Repository\Master\PageMaxRepository; |
||
36 | use Eccube\Repository\Master\ProductStatusRepository; |
||
37 | use Eccube\Repository\ProductClassRepository; |
||
38 | use Eccube\Repository\ProductImageRepository; |
||
39 | use Eccube\Repository\ProductRepository; |
||
40 | use Eccube\Repository\TagRepository; |
||
41 | use Eccube\Repository\TaxRuleRepository; |
||
42 | use Eccube\Service\CsvExportService; |
||
43 | use Eccube\Util\CacheUtil; |
||
44 | use Eccube\Util\FormUtil; |
||
45 | use Knp\Component\Pager\Paginator; |
||
46 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
||
47 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; |
||
48 | use Symfony\Component\Filesystem\Filesystem; |
||
49 | use Symfony\Component\HttpFoundation\File\File; |
||
50 | use Symfony\Component\HttpFoundation\RedirectResponse; |
||
51 | use Symfony\Component\HttpFoundation\Request; |
||
52 | use Symfony\Component\HttpFoundation\StreamedResponse; |
||
53 | use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
||
54 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
||
55 | use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException; |
||
56 | use Symfony\Component\Routing\Annotation\Route; |
||
57 | use Symfony\Component\Routing\RouterInterface; |
||
58 | |||
59 | class ProductController extends AbstractController |
||
60 | { |
||
61 | /** |
||
62 | * @var CsvExportService |
||
63 | */ |
||
64 | protected $csvExportService; |
||
65 | |||
66 | /** |
||
67 | * @var ProductClassRepository |
||
68 | */ |
||
69 | protected $productClassRepository; |
||
70 | |||
71 | /** |
||
72 | * @var ProductImageRepository |
||
73 | */ |
||
74 | protected $productImageRepository; |
||
75 | |||
76 | /** |
||
77 | * @var TaxRuleRepository |
||
78 | */ |
||
79 | protected $taxRuleRepository; |
||
80 | |||
81 | /** |
||
82 | * @var CategoryRepository |
||
83 | */ |
||
84 | protected $categoryRepository; |
||
85 | |||
86 | /** |
||
87 | * @var ProductRepository |
||
88 | */ |
||
89 | protected $productRepository; |
||
90 | |||
91 | /** |
||
92 | * @var BaseInfo |
||
93 | */ |
||
94 | protected $BaseInfo; |
||
95 | |||
96 | /** |
||
97 | * @var PageMaxRepository |
||
98 | */ |
||
99 | protected $pageMaxRepository; |
||
100 | |||
101 | /** |
||
102 | * @var ProductStatusRepository |
||
103 | */ |
||
104 | protected $productStatusRepository; |
||
105 | |||
106 | /** |
||
107 | * @var TagRepository |
||
108 | */ |
||
109 | protected $tagRepository; |
||
110 | |||
111 | /** |
||
112 | * ProductController constructor. |
||
113 | * |
||
114 | * @param CsvExportService $csvExportService |
||
115 | * @param ProductClassRepository $productClassRepository |
||
116 | * @param ProductImageRepository $productImageRepository |
||
117 | * @param TaxRuleRepository $taxRuleRepository |
||
118 | * @param CategoryRepository $categoryRepository |
||
119 | * @param ProductRepository $productRepository |
||
120 | * @param BaseInfoRepository $baseInfoRepository |
||
121 | * @param PageMaxRepository $pageMaxRepository |
||
122 | * @param ProductStatusRepository $productStatusRepository |
||
123 | * @param TagRepository $tagRepository |
||
124 | 26 | */ |
|
125 | View Code Duplication | public function __construct( |
|
0 ignored issues
–
show
|
|||
126 | CsvExportService $csvExportService, |
||
127 | ProductClassRepository $productClassRepository, |
||
128 | ProductImageRepository $productImageRepository, |
||
129 | TaxRuleRepository $taxRuleRepository, |
||
130 | CategoryRepository $categoryRepository, |
||
131 | ProductRepository $productRepository, |
||
132 | BaseInfoRepository $baseInfoRepository, |
||
133 | PageMaxRepository $pageMaxRepository, |
||
134 | ProductStatusRepository $productStatusRepository, |
||
135 | TagRepository $tagRepository |
||
136 | 26 | ) { |
|
137 | 26 | $this->csvExportService = $csvExportService; |
|
138 | 26 | $this->productClassRepository = $productClassRepository; |
|
139 | 26 | $this->productImageRepository = $productImageRepository; |
|
140 | 26 | $this->taxRuleRepository = $taxRuleRepository; |
|
141 | 26 | $this->categoryRepository = $categoryRepository; |
|
142 | 26 | $this->productRepository = $productRepository; |
|
143 | 26 | $this->BaseInfo = $baseInfoRepository->get(); |
|
144 | 26 | $this->pageMaxRepository = $pageMaxRepository; |
|
145 | 26 | $this->productStatusRepository = $productStatusRepository; |
|
146 | $this->tagRepository = $tagRepository; |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * @Route("/%eccube_admin_route%/product", name="admin_product") |
||
151 | * @Route("/%eccube_admin_route%/product/page/{page_no}", requirements={"page_no" = "\d+"}, name="admin_product_page") |
||
152 | * @Template("@admin/Product/index.twig") |
||
153 | 4 | */ |
|
154 | public function index(Request $request, $page_no = null, Paginator $paginator) |
||
155 | 4 | { |
|
156 | 4 | $builder = $this->formFactory |
|
157 | ->createBuilder(SearchProductType::class); |
||
158 | 4 | ||
159 | $event = new EventArgs( |
||
160 | 4 | [ |
|
161 | 'builder' => $builder, |
||
162 | 4 | ], |
|
163 | $request |
||
164 | 4 | ); |
|
165 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_INITIALIZE, $event); |
||
166 | 4 | ||
167 | $searchForm = $builder->getForm(); |
||
168 | |||
169 | /** |
||
170 | * ページの表示件数は, 以下の順に優先される. |
||
171 | * - リクエストパラメータ |
||
172 | * - セッション |
||
173 | * - デフォルト値 |
||
174 | * また, セッションに保存する際は mtb_page_maxと照合し, 一致した場合のみ保存する. |
||
175 | 4 | **/ |
|
176 | 4 | $page_count = $this->session->get('eccube.admin.order.search.page_count', |
|
177 | $this->eccubeConfig->get('eccube_default_page_count')); |
||
178 | 4 | ||
179 | 4 | $page_count_param = (int) $request->get('page_count'); |
|
180 | $pageMaxis = $this->pageMaxRepository->findAll(); |
||
181 | 4 | ||
182 | View Code Duplication | if ($page_count_param) { |
|
183 | foreach ($pageMaxis as $pageMax) { |
||
184 | if ($page_count_param == $pageMax->getName()) { |
||
185 | $page_count = $pageMax->getName(); |
||
186 | $this->session->set('eccube.admin.order.search.page_count', $page_count); |
||
187 | break; |
||
188 | } |
||
189 | } |
||
190 | } |
||
191 | 4 | ||
192 | 2 | if ('POST' === $request->getMethod()) { |
|
193 | $searchForm->handleRequest($request); |
||
194 | 2 | ||
195 | View Code Duplication | if ($searchForm->isValid()) { |
|
196 | /** |
||
197 | * 検索が実行された場合は, セッションに検索条件を保存する. |
||
198 | * ページ番号は最初のページ番号に初期化する. |
||
199 | 2 | */ |
|
200 | 2 | $page_no = 1; |
|
201 | $searchData = $searchForm->getData(); |
||
202 | |||
203 | 2 | // 検索条件, ページ番号をセッションに保持. |
|
204 | 2 | $this->session->set('eccube.admin.product.search', FormUtil::getViewData($searchForm)); |
|
205 | $this->session->set('eccube.admin.product.search.page_no', $page_no); |
||
206 | } else { |
||
207 | // 検索エラーの際は, 詳細検索枠を開いてエラー表示する. |
||
208 | 2 | return [ |
|
209 | 'searchForm' => $searchForm->createView(), |
||
210 | 'pagination' => [], |
||
211 | 'pageMaxis' => $pageMaxis, |
||
212 | 'page_no' => $page_no, |
||
213 | 'page_count' => $page_count, |
||
214 | 'has_errors' => true, |
||
215 | ]; |
||
216 | } |
||
217 | 2 | View Code Duplication | } else { |
218 | if (null !== $page_no || $request->get('resume')) { |
||
219 | /* |
||
220 | * ページ送りの場合または、他画面から戻ってきた場合は, セッションから検索条件を復旧する. |
||
221 | 1 | */ |
|
222 | if ($page_no) { |
||
223 | 1 | // ページ送りで遷移した場合. |
|
224 | $this->session->set('eccube.admin.product.search.page_no', (int) $page_no); |
||
225 | } else { |
||
226 | // 他画面から遷移した場合. |
||
227 | $page_no = $this->session->get('eccube.admin.product.search.page_no', 1); |
||
228 | 1 | } |
|
229 | 1 | $viewData = $this->session->get('eccube.admin.product.search', []); |
|
230 | $searchData = FormUtil::submitAndGetData($searchForm, $viewData); |
||
231 | } else { |
||
232 | /** |
||
233 | * 初期表示の場合. |
||
234 | 1 | */ |
|
235 | $page_no = 1; |
||
236 | 1 | // submit default value |
|
237 | 1 | $viewData = FormUtil::getViewData($searchForm); |
|
238 | $searchData = FormUtil::submitAndGetData($searchForm, $viewData); |
||
239 | |||
240 | 1 | // セッション中の検索条件, ページ番号を初期化. |
|
241 | 1 | $this->session->set('eccube.admin.product.search', $viewData); |
|
242 | $this->session->set('eccube.admin.product.search.page_no', $page_no); |
||
243 | } |
||
244 | } |
||
245 | 4 | ||
246 | $qb = $this->productRepository->getQueryBuilderBySearchDataForAdmin($searchData); |
||
247 | 4 | ||
248 | $event = new EventArgs( |
||
249 | 4 | [ |
|
250 | 4 | 'qb' => $qb, |
|
251 | 'searchData' => $searchData, |
||
252 | 4 | ], |
|
253 | $request |
||
254 | ); |
||
255 | 4 | ||
256 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_INDEX_SEARCH, $event); |
||
257 | 4 | ||
258 | 4 | $pagination = $paginator->paginate( |
|
259 | 4 | $qb, |
|
260 | 4 | $page_no, |
|
261 | $page_count |
||
262 | ); |
||
263 | |||
264 | 4 | return [ |
|
265 | 4 | 'searchForm' => $searchForm->createView(), |
|
266 | 4 | 'pagination' => $pagination, |
|
267 | 4 | 'pageMaxis' => $pageMaxis, |
|
268 | 4 | 'page_no' => $page_no, |
|
269 | 'page_count' => $page_count, |
||
270 | 'has_errors' => false, |
||
271 | ]; |
||
272 | } |
||
273 | |||
274 | /** |
||
275 | * @Route("/%eccube_admin_route%/product/classes/{id}/load", name="admin_product_classes_load", methods={"GET"}, requirements={"id" = "\d+"}) |
||
276 | * @Template("@admin/Product/product_class_popup.twig") |
||
277 | * @ParamConverter("Product") |
||
278 | */ |
||
279 | 1 | public function loadProductClasses(Request $request, Product $Product) |
|
280 | { |
||
281 | 1 | if (!$request->isXmlHttpRequest()) { |
|
282 | throw new BadRequestHttpException(); |
||
283 | } |
||
284 | |||
285 | 1 | $data = []; |
|
286 | /** @var $Product ProductRepository */ |
||
287 | 1 | if (!$Product) { |
|
288 | throw new NotFoundHttpException(); |
||
289 | } |
||
290 | |||
291 | 1 | if ($Product->hasProductClass()) { |
|
0 ignored issues
–
show
The method
hasProductClass does not exist on object<Eccube\Repository\ProductRepository> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
Loading history...
|
|||
292 | 1 | $class = $Product->getProductClasses(); |
|
0 ignored issues
–
show
The method
getProductClasses does not exist on object<Eccube\Repository\ProductRepository> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
Loading history...
|
|||
293 | 1 | foreach ($class as $item) { |
|
294 | 1 | if ($item['visible']) { |
|
295 | 1 | $data[] = $item; |
|
296 | } |
||
297 | } |
||
298 | } |
||
299 | |||
300 | return [ |
||
301 | 1 | 'data' => $data, |
|
302 | ]; |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * @Route("/%eccube_admin_route%/product/product/image/add", name="admin_product_image_add", methods={"POST"}) |
||
307 | */ |
||
308 | public function addImage(Request $request) |
||
309 | { |
||
310 | if (!$request->isXmlHttpRequest()) { |
||
311 | throw new BadRequestHttpException(); |
||
312 | } |
||
313 | |||
314 | $images = $request->files->get('admin_product'); |
||
315 | |||
316 | $allowExtensions = ['gif', 'jpg', 'jpeg', 'png']; |
||
317 | $files = []; |
||
318 | if (count($images) > 0) { |
||
319 | foreach ($images as $img) { |
||
320 | foreach ($img as $image) { |
||
321 | //ファイルフォーマット検証 |
||
322 | $mimeType = $image->getMimeType(); |
||
323 | if (0 !== strpos($mimeType, 'image')) { |
||
324 | throw new UnsupportedMediaTypeHttpException(); |
||
325 | } |
||
326 | |||
327 | // 拡張子 |
||
328 | $extension = $image->getClientOriginalExtension(); |
||
329 | if (!in_array(strtolower($extension), $allowExtensions)) { |
||
330 | throw new UnsupportedMediaTypeHttpException(); |
||
331 | } |
||
332 | |||
333 | $filename = date('mdHis').uniqid('_').'.'.$extension; |
||
334 | $image->move($this->eccubeConfig['eccube_temp_image_dir'], $filename); |
||
335 | $files[] = $filename; |
||
336 | } |
||
337 | } |
||
338 | } |
||
339 | |||
340 | $event = new EventArgs( |
||
341 | [ |
||
342 | 'images' => $images, |
||
343 | 'files' => $files, |
||
344 | ], |
||
345 | $request |
||
346 | ); |
||
347 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_ADD_IMAGE_COMPLETE, $event); |
||
348 | $files = $event->getArgument('files'); |
||
349 | |||
350 | return $this->json(['files' => $files], 200); |
||
351 | } |
||
352 | |||
353 | 18 | /** |
|
354 | * @Route("/%eccube_admin_route%/product/product/new", name="admin_product_product_new") |
||
355 | 18 | * @Route("/%eccube_admin_route%/product/product/{id}/edit", requirements={"id" = "\d+"}, name="admin_product_product_edit") |
|
356 | 18 | * @Template("@admin/Product/product.twig") |
|
357 | 5 | */ |
|
358 | 5 | public function edit(Request $request, $id = null, RouterInterface $router, CacheUtil $cacheUtil) |
|
359 | 5 | { |
|
360 | $has_class = false; |
||
361 | 5 | if (is_null($id)) { |
|
362 | 5 | $Product = new Product(); |
|
363 | $ProductClass = new ProductClass(); |
||
364 | 5 | $ProductStatus = $this->productStatusRepository->find(ProductStatus::DISPLAY_HIDE); |
|
365 | 5 | $Product |
|
366 | 5 | ->addProductClass($ProductClass) |
|
367 | 5 | ->setStatus($ProductStatus); |
|
0 ignored issues
–
show
It seems like
$ProductStatus defined by $this->productStatusRepo...ctStatus::DISPLAY_HIDE) on line 364 can also be of type object ; however, Eccube\Entity\Product::setStatus() does only seem to accept null|object<Eccube\Entity\Master\ProductStatus> , 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...
|
|||
368 | 5 | $ProductClass |
|
369 | 5 | ->setVisible(true) |
|
370 | ->setStockUnlimited(true) |
||
371 | 13 | ->setProduct($Product); |
|
372 | 13 | $ProductStock = new ProductStock(); |
|
373 | $ProductClass->setProductStock($ProductStock); |
||
374 | $ProductStock->setProductClass($ProductClass); |
||
375 | } else { |
||
376 | 13 | $Product = $this->productRepository->find($id); |
|
377 | 13 | if (!$Product) { |
|
378 | 11 | throw new NotFoundHttpException(); |
|
379 | 11 | } |
|
380 | 11 | // 規格無しの商品の場合は、デフォルト規格を表示用に取得する |
|
381 | $has_class = $Product->hasProductClass(); |
||
382 | if (!$has_class) { |
||
383 | 11 | $ProductClasses = $Product->getProductClasses(); |
|
384 | 11 | foreach ($ProductClasses as $pc) { |
|
385 | 11 | if (!is_null($pc->getClassCategory1())) { |
|
386 | continue; |
||
387 | } |
||
388 | 11 | if ($pc->isVisible()) { |
|
389 | 6 | $ProductClass = $pc; |
|
390 | break; |
||
391 | 11 | } |
|
392 | } |
||
393 | if ($this->BaseInfo->isOptionProductTaxRule() && $ProductClass->getTaxRule()) { |
||
394 | $ProductClass->setTaxRate($ProductClass->getTaxRule()->getTaxRate()); |
||
0 ignored issues
–
show
The variable
$ProductClass does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
395 | 18 | } |
|
396 | 18 | $ProductStock = $ProductClass->getProductStock(); |
|
397 | } |
||
398 | } |
||
399 | 18 | ||
400 | 2 | $builder = $this->formFactory |
|
401 | ->createBuilder(ProductType::class, $Product); |
||
402 | |||
403 | 18 | // 規格あり商品の場合、規格関連情報をFormから除外 |
|
404 | if ($has_class) { |
||
405 | 18 | $builder->remove('class'); |
|
406 | 18 | } |
|
407 | |||
408 | 18 | $event = new EventArgs( |
|
409 | [ |
||
410 | 18 | 'builder' => $builder, |
|
411 | 'Product' => $Product, |
||
412 | 18 | ], |
|
413 | $request |
||
414 | 18 | ); |
|
415 | 16 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_INITIALIZE, $event); |
|
416 | 16 | ||
417 | $form = $builder->getForm(); |
||
418 | |||
419 | if (!$has_class) { |
||
420 | 18 | $ProductClass->setStockUnlimited($ProductClass->isStockUnlimited()); |
|
421 | 18 | $form['class']->setData($ProductClass); |
|
422 | 18 | } |
|
423 | 13 | ||
424 | // ファイルの登録 |
||
425 | 18 | $images = []; |
|
426 | $ProductImages = $Product->getProductImage(); |
||
427 | 18 | foreach ($ProductImages as $ProductImage) { |
|
428 | 18 | $images[] = $ProductImage->getFileName(); |
|
429 | 18 | } |
|
430 | $form['images']->setData($images); |
||
431 | 13 | ||
432 | $categories = []; |
||
433 | 18 | $ProductCategories = $Product->getProductCategories(); |
|
434 | foreach ($ProductCategories as $ProductCategory) { |
||
435 | 18 | /* @var $ProductCategory \Eccube\Entity\ProductCategory */ |
|
436 | 18 | $categories[] = $ProductCategory->getCategory(); |
|
437 | } |
||
438 | 18 | $form['Category']->setData($categories); |
|
439 | 13 | ||
440 | 13 | $Tags = $Product->getTags(); |
|
441 | 13 | $form['Tag']->setData($Tags); |
|
442 | 13 | ||
443 | if ('POST' === $request->getMethod()) { |
||
444 | 13 | $form->handleRequest($request); |
|
445 | 13 | if ($form->isValid()) { |
|
446 | log_info('商品登録開始', [$id]); |
||
447 | $Product = $form->getData(); |
||
448 | 13 | ||
449 | 12 | if (!$has_class) { |
|
450 | 8 | $ProductClass = $form['class']->getData(); |
|
451 | 4 | ||
452 | // 個別消費税 |
||
453 | 4 | if ($this->BaseInfo->isOptionProductTaxRule()) { |
|
454 | 4 | if ($ProductClass->getTaxRate() !== null) { |
|
455 | 4 | if ($ProductClass->getTaxRule()) { |
|
456 | 4 | $ProductClass->getTaxRule()->setTaxRate($ProductClass->getTaxRate()); |
|
457 | 4 | } else { |
|
458 | 4 | $taxrule = $this->taxRuleRepository->newTaxRule(); |
|
459 | $taxrule->setTaxRate($ProductClass->getTaxRate()); |
||
460 | $taxrule->setApplyDate(new \DateTime()); |
||
461 | 8 | $taxrule->setProduct($Product); |
|
462 | $taxrule->setProductClass($ProductClass); |
||
463 | 4 | $ProductClass->setTaxRule($taxrule); |
|
464 | 2 | } |
|
465 | 2 | ||
466 | $ProductClass->getTaxRule()->setTaxRate($ProductClass->getTaxRate()); |
||
467 | } else { |
||
468 | if ($ProductClass->getTaxRule()) { |
||
469 | 13 | $this->taxRuleRepository->delete($ProductClass->getTaxRule()); |
|
470 | $ProductClass->setTaxRule(null); |
||
471 | } |
||
472 | 13 | } |
|
473 | } |
||
474 | $this->entityManager->persist($ProductClass); |
||
475 | |||
476 | 13 | // 在庫情報を作成 |
|
477 | if (!$ProductClass->isStockUnlimited()) { |
||
478 | 13 | $ProductStock->setStock($ProductClass->getStock()); |
|
0 ignored issues
–
show
The variable
$ProductStock does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
479 | } else { |
||
480 | // 在庫無制限時はnullを設定 |
||
481 | $ProductStock->setStock(null); |
||
482 | } |
||
483 | $this->entityManager->persist($ProductStock); |
||
484 | 13 | } |
|
485 | 10 | ||
486 | 10 | // カテゴリの登録 |
|
487 | // 一度クリア |
||
488 | 13 | /* @var $Product \Eccube\Entity\Product */ |
|
489 | 13 | foreach ($Product->getProductCategories() as $ProductCategory) { |
|
490 | $Product->removeProductCategory($ProductCategory); |
||
491 | 13 | $this->entityManager->remove($ProductCategory); |
|
492 | 13 | } |
|
493 | 13 | $this->entityManager->persist($Product); |
|
494 | 13 | $this->entityManager->flush(); |
|
495 | |||
496 | $count = 1; |
||
497 | $Categories = $form->get('Category')->getData(); |
||
498 | $categoriesIdList = []; |
||
499 | foreach ($Categories as $Category) { |
||
500 | View Code Duplication | foreach ($Category->getPath() as $ParentCategory) { |
|
501 | if (!isset($categoriesIdList[$ParentCategory->getId()])) { |
||
502 | $ProductCategory = $this->createProductCategory($Product, $ParentCategory, $count); |
||
503 | $this->entityManager->persist($ProductCategory); |
||
504 | $count++; |
||
505 | /* @var $Product \Eccube\Entity\Product */ |
||
506 | $Product->addProductCategory($ProductCategory); |
||
507 | $categoriesIdList[$ParentCategory->getId()] = true; |
||
508 | } |
||
509 | } |
||
510 | if (!isset($categoriesIdList[$Category->getId()])) { |
||
511 | $ProductCategory = $this->createProductCategory($Product, $Category, $count); |
||
512 | $this->entityManager->persist($ProductCategory); |
||
513 | $count++; |
||
514 | /* @var $Product \Eccube\Entity\Product */ |
||
515 | $Product->addProductCategory($ProductCategory); |
||
516 | 13 | $categoriesIdList[$ParentCategory->getId()] = true; |
|
0 ignored issues
–
show
The variable
$ParentCategory seems to be defined by a foreach iteration on line 500 . Are you sure the iterator is never empty, otherwise this variable is not defined?
It seems like you are relying on a variable being defined by an iteration: foreach ($a as $b) {
}
// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.
// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}
// $b is now guaranteed to be defined here.
Loading history...
|
|||
517 | 13 | } |
|
518 | } |
||
519 | |||
520 | // 画像の登録 |
||
521 | $add_images = $form->get('add_images')->getData(); |
||
522 | foreach ($add_images as $add_image) { |
||
523 | $ProductImage = new \Eccube\Entity\ProductImage(); |
||
524 | $ProductImage |
||
525 | ->setFileName($add_image) |
||
526 | ->setProduct($Product) |
||
527 | ->setSortNo(1); |
||
528 | $Product->addProductImage($ProductImage); |
||
529 | $this->entityManager->persist($ProductImage); |
||
530 | |||
531 | // 移動 |
||
532 | 13 | $file = new File($this->eccubeConfig['eccube_temp_image_dir'].'/'.$add_image); |
|
533 | 13 | $file->move($this->eccubeConfig['eccube_save_image_dir']); |
|
534 | } |
||
535 | |||
536 | // 画像の削除 |
||
537 | $delete_images = $form->get('delete_images')->getData(); |
||
538 | foreach ($delete_images as $delete_image) { |
||
539 | $ProductImage = $this->productImageRepository |
||
540 | ->findOneBy(['file_name' => $delete_image]); |
||
541 | |||
542 | // 追加してすぐに削除した画像は、Entityに追加されない |
||
543 | if ($ProductImage instanceof ProductImage) { |
||
544 | $Product->removeProductImage($ProductImage); |
||
545 | $this->entityManager->remove($ProductImage); |
||
546 | } |
||
547 | $this->entityManager->persist($Product); |
||
548 | 13 | ||
549 | 13 | // 削除 |
|
550 | $fs = new Filesystem(); |
||
551 | 13 | $fs->remove($this->eccubeConfig['eccube_save_image_dir'].'/'.$delete_image); |
|
552 | 13 | } |
|
553 | $this->entityManager->persist($Product); |
||
554 | $this->entityManager->flush(); |
||
555 | |||
556 | $sortNos = $request->get('sort_no_images'); |
||
557 | if ($sortNos) { |
||
558 | foreach ($sortNos as $sortNo) { |
||
559 | list($filename, $sortNo_val) = explode('//', $sortNo); |
||
560 | $ProductImage = $this->productImageRepository |
||
561 | ->findOneBy([ |
||
562 | 'file_name' => $filename, |
||
563 | 'Product' => $Product, |
||
564 | 13 | ]); |
|
565 | $ProductImage->setSortNo($sortNo_val); |
||
566 | $this->entityManager->persist($ProductImage); |
||
0 ignored issues
–
show
It seems like
$ProductImage defined by $this->productImageRepos...'Product' => $Product)) on line 560 can also be of type null ; however, Doctrine\Common\Persiste...bjectManager::persist() does only seem to accept object , 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...
|
|||
567 | } |
||
568 | 13 | } |
|
569 | 13 | $this->entityManager->flush(); |
|
570 | 1 | ||
571 | 1 | // 商品タグの登録 |
|
572 | // 商品タグを一度クリア |
||
573 | $ProductTags = $Product->getProductTag(); |
||
574 | foreach ($ProductTags as $ProductTag) { |
||
575 | 13 | $Product->removeProductTag($ProductTag); |
|
576 | 13 | $this->entityManager->remove($ProductTag); |
|
577 | 13 | } |
|
578 | |||
579 | 13 | // 商品タグの登録 |
|
580 | 13 | $Tags = $form->get('Tag')->getData(); |
|
581 | 13 | foreach ($Tags as $Tag) { |
|
582 | 13 | $ProductTag = new ProductTag(); |
|
583 | $ProductTag |
||
584 | ->setProduct($Product) |
||
585 | 13 | ->setTag($Tag); |
|
586 | 13 | $Product->addProductTag($ProductTag); |
|
587 | $this->entityManager->persist($ProductTag); |
||
588 | 13 | } |
|
589 | |||
590 | 13 | $Product->setUpdateDate(new \DateTime()); |
|
591 | $this->entityManager->flush(); |
||
592 | 13 | ||
593 | 13 | log_info('商品登録完了', [$id]); |
|
594 | |||
595 | 13 | $event = new EventArgs( |
|
596 | [ |
||
597 | 13 | 'form' => $form, |
|
598 | 'Product' => $Product, |
||
599 | 13 | ], |
|
600 | $request |
||
601 | 13 | ); |
|
602 | 1 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_COMPLETE, $event); |
|
603 | |||
604 | $this->addSuccess('admin.common.save_complete', 'admin'); |
||
605 | 13 | ||
606 | View Code Duplication | if ($returnLink = $form->get('return_link')->getData()) { |
|
607 | try { |
||
608 | // $returnLinkはpathの形式で渡される. pathが存在するかをルータでチェックする. |
||
609 | $pattern = '/^'.preg_quote($request->getBasePath(), '/').'/'; |
||
610 | 5 | $returnLink = preg_replace($pattern, '', $returnLink); |
|
611 | 5 | $result = $router->match($returnLink); |
|
0 ignored issues
–
show
It seems like
$returnLink defined by preg_replace($pattern, '', $returnLink) on line 610 can also be of type array<integer,string> ; however, Symfony\Component\Routin...tcherInterface::match() does only seem to accept string , 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...
|
|||
612 | // パラメータのみ抽出 |
||
613 | 5 | $params = array_filter($result, function ($key) { |
|
614 | return 0 !== \strpos($key, '_'); |
||
615 | 5 | }, ARRAY_FILTER_USE_KEY); |
|
616 | 5 | ||
617 | // pathからurlを再構築してリダイレクト. |
||
618 | 5 | return $this->redirectToRoute($result['_route'], $params); |
|
619 | } catch (\Exception $e) { |
||
620 | 5 | // マッチしない場合はログ出力してスキップ. |
|
621 | log_warning('URLの形式が不正です。'); |
||
622 | 5 | } |
|
623 | } |
||
624 | 5 | ||
625 | $cacheUtil->clearDoctrineCache(); |
||
626 | |||
627 | return $this->redirectToRoute('admin_product_product_edit', ['id' => $Product->getId()]); |
||
628 | } |
||
629 | 5 | } |
|
630 | |||
631 | // 検索結果の保持 |
||
632 | 5 | $builder = $this->formFactory |
|
633 | 5 | ->createBuilder(SearchProductType::class); |
|
634 | 3 | ||
635 | 5 | $event = new EventArgs( |
|
636 | [ |
||
637 | 'builder' => $builder, |
||
638 | 5 | 'Product' => $Product, |
|
639 | 5 | ], |
|
640 | 5 | $request |
|
641 | 5 | ); |
|
642 | 5 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_EDIT_SEARCH, $event); |
|
643 | 5 | ||
644 | 5 | $searchForm = $builder->getForm(); |
|
645 | 5 | ||
646 | 5 | if ('POST' === $request->getMethod()) { |
|
647 | $searchForm->handleRequest($request); |
||
648 | } |
||
649 | |||
650 | // Get Tags |
||
651 | $TagsList = $this->tagRepository->getList(); |
||
652 | |||
653 | // ツリー表示のため、ルートからのカテゴリを取得 |
||
654 | 1 | $TopCategories = $this->categoryRepository->getList(null); |
|
655 | $ChoicedCategoryIds = array_map(function ($Category) { |
||
656 | 1 | return $Category->getId(); |
|
657 | 1 | }, $form->get('Category')->getData()); |
|
658 | 1 | ||
659 | 1 | return [ |
|
660 | 1 | 'Product' => $Product, |
|
661 | 1 | 'Tags' => $Tags, |
|
662 | 'TagsList' => $TagsList, |
||
663 | 1 | 'form' => $form->createView(), |
|
664 | 'searchForm' => $searchForm->createView(), |
||
665 | 1 | 'has_class' => $has_class, |
|
666 | 1 | 'id' => $id, |
|
667 | 'TopCategories' => $TopCategories, |
||
668 | 'ChoicedCategoryIds' => $ChoicedCategoryIds, |
||
669 | ]; |
||
670 | } |
||
671 | |||
672 | /** |
||
673 | * @Route("/%eccube_admin_route%/product/product/{id}/delete", requirements={"id" = "\d+"}, name="admin_product_product_delete", methods={"DELETE"}) |
||
674 | */ |
||
675 | public function delete(Request $request, $id = null, CacheUtil $cacheUtil) |
||
676 | { |
||
677 | $this->isTokenValid(); |
||
678 | $session = $request->getSession(); |
||
679 | 1 | $page_no = intval($session->get('eccube.admin.product.search.page_no')); |
|
680 | 1 | $page_no = $page_no ? $page_no : Constant::ENABLED; |
|
681 | $message = null; |
||
682 | 1 | $success = false; |
|
683 | 1 | ||
684 | if (!is_null($id)) { |
||
685 | /* @var $Product \Eccube\Entity\Product */ |
||
686 | 1 | $Product = $this->productRepository->find($id); |
|
687 | 1 | View Code Duplication | if (!$Product) { |
688 | if ($request->isXmlHttpRequest()) { |
||
689 | 1 | $message = trans('admin.common.delete_error_already_deleted'); |
|
690 | |||
691 | 1 | return $this->json(['success' => $success, 'message' => $message]); |
|
692 | 1 | } else { |
|
693 | 1 | $this->deleteMessage(); |
|
694 | $rUrl = $this->generateUrl('admin_product_page', ['page_no' => $page_no]).'?resume='.Constant::ENABLED; |
||
695 | 1 | ||
696 | return $this->redirect($rUrl); |
||
697 | 1 | } |
|
698 | 1 | } |
|
699 | |||
700 | if ($Product instanceof Product) { |
||
701 | 1 | log_info('商品削除開始', [$id]); |
|
702 | |||
703 | 1 | $deleteImages = $Product->getProductImage(); |
|
704 | 1 | $ProductClasses = $Product->getProductClasses(); |
|
705 | 1 | ||
706 | try { |
||
707 | $this->productRepository->delete($Product); |
||
708 | $this->entityManager->flush(); |
||
709 | |||
710 | 1 | $event = new EventArgs( |
|
711 | [ |
||
712 | 1 | 'Product' => $Product, |
|
713 | 1 | 'ProductClass' => $ProductClasses, |
|
714 | 'deleteImages' => $deleteImages, |
||
715 | ], |
||
716 | 1 | $request |
|
717 | ); |
||
718 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_DELETE_COMPLETE, $event); |
||
719 | $deleteImages = $event->getArgument('deleteImages'); |
||
720 | 1 | ||
721 | // 画像ファイルの削除(commit後に削除させる) |
||
722 | View Code Duplication | foreach ($deleteImages as $deleteImage) { |
|
723 | try { |
||
724 | $fs = new Filesystem(); |
||
725 | $fs->remove($this->eccubeConfig['eccube_save_image_dir'].'/'.$deleteImage); |
||
726 | } catch (\Exception $e) { |
||
727 | 1 | // エラーが発生しても無視する |
|
728 | } |
||
729 | } |
||
730 | 1 | ||
731 | 1 | log_info('商品削除完了', [$id]); |
|
732 | |||
733 | $success = true; |
||
734 | $message = trans('admin.common.delete_complete'); |
||
735 | |||
736 | 1 | $cacheUtil->clearDoctrineCache(); |
|
737 | } catch (ForeignKeyConstraintViolationException $e) { |
||
738 | 1 | log_info('商品削除エラー', [$id]); |
|
739 | $message = trans('admin.common.delete_error_foreign_key', ['%name%' => $Product->getName()]); |
||
740 | } |
||
741 | } else { |
||
742 | log_info('商品削除エラー', [$id]); |
||
743 | $message = trans('admin.common.delete_error'); |
||
744 | } |
||
745 | } else { |
||
746 | 1 | log_info('商品削除エラー', [$id]); |
|
747 | $message = trans('admin.common.delete_error'); |
||
748 | 1 | } |
|
749 | |||
750 | 1 | View Code Duplication | if ($request->isXmlHttpRequest()) { |
751 | 1 | return $this->json(['success' => $success, 'message' => $message]); |
|
752 | 1 | } else { |
|
753 | 1 | if ($success) { |
|
754 | 1 | $this->addSuccess($message, 'admin'); |
|
755 | 1 | } else { |
|
756 | 1 | $this->addError($message, 'admin'); |
|
757 | } |
||
758 | 1 | ||
759 | 1 | $rUrl = $this->generateUrl('admin_product_page', ['page_no' => $page_no]).'?resume='.Constant::ENABLED; |
|
760 | 1 | ||
761 | return $this->redirect($rUrl); |
||
762 | } |
||
763 | } |
||
764 | 1 | ||
765 | 1 | /** |
|
766 | 1 | * @Route("/%eccube_admin_route%/product/product/{id}/copy", requirements={"id" = "\d+"}, name="admin_product_product_copy", methods={"POST"}) |
|
767 | */ |
||
768 | public function copy(Request $request, $id = null) |
||
769 | 1 | { |
|
770 | $this->isTokenValid(); |
||
771 | 1 | ||
772 | 1 | if (!is_null($id)) { |
|
773 | 1 | $Product = $this->productRepository->find($id); |
|
774 | if ($Product instanceof Product) { |
||
775 | $CopyProduct = clone $Product; |
||
776 | 1 | $CopyProduct->copy(); |
|
777 | 1 | $ProductStatus = $this->productStatusRepository->find(ProductStatus::DISPLAY_HIDE); |
|
778 | 1 | $CopyProduct->setStatus($ProductStatus); |
|
0 ignored issues
–
show
It seems like
$ProductStatus defined by $this->productStatusRepo...ctStatus::DISPLAY_HIDE) on line 777 can also be of type object ; however, Eccube\Entity\Product::setStatus() does only seem to accept null|object<Eccube\Entity\Master\ProductStatus> , 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...
|
|||
779 | 1 | ||
780 | 1 | $CopyProductCategories = $CopyProduct->getProductCategories(); |
|
781 | 1 | foreach ($CopyProductCategories as $Category) { |
|
782 | $this->entityManager->persist($Category); |
||
783 | 1 | } |
|
784 | 1 | ||
785 | // 規格あり商品の場合は, デフォルトの商品規格を取得し登録する. |
||
786 | if ($CopyProduct->hasProductClass()) { |
||
787 | $dummyClass = $this->productClassRepository->findOneBy([ |
||
788 | 'visible' => false, |
||
789 | 'ClassCategory1' => null, |
||
790 | 1 | 'ClassCategory2' => null, |
|
791 | 'Product' => $Product, |
||
792 | 1 | ]); |
|
793 | 1 | $dummyClass = clone $dummyClass; |
|
794 | $dummyClass->setProduct($CopyProduct); |
||
795 | 1 | $CopyProduct->addProductClass($dummyClass); |
|
796 | 1 | } |
|
797 | |||
798 | 1 | $CopyProductClasses = $CopyProduct->getProductClasses(); |
|
799 | 1 | foreach ($CopyProductClasses as $Class) { |
|
800 | 1 | $Stock = $Class->getProductStock(); |
|
801 | $CopyStock = clone $Stock; |
||
802 | $CopyStock->setProductClass($Class); |
||
803 | 1 | $this->entityManager->persist($CopyStock); |
|
804 | |||
805 | 1 | $TaxRule = $Class->getTaxRule(); |
|
806 | if ($TaxRule) { |
||
807 | 1 | $CopyTaxRule = clone $TaxRule; |
|
808 | 1 | $CopyTaxRule->setProductClass($Class); |
|
809 | $CopyTaxRule->setProduct($CopyProduct); |
||
810 | $this->entityManager->persist($CopyTaxRule); |
||
811 | } |
||
812 | 1 | $this->entityManager->persist($Class); |
|
813 | } |
||
814 | 1 | $Images = $CopyProduct->getProductImage(); |
|
815 | foreach ($Images as $Image) { |
||
816 | 1 | // 画像ファイルを新規作成 |
|
817 | $extension = pathinfo($Image->getFileName(), PATHINFO_EXTENSION); |
||
818 | 1 | $filename = date('mdHis').uniqid('_').'.'.$extension; |
|
819 | 1 | try { |
|
820 | 1 | $fs = new Filesystem(); |
|
821 | 1 | $fs->copy($this->eccubeConfig['eccube_save_image_dir'].'/'.$Image->getFileName(), $this->eccubeConfig['eccube_save_image_dir'].'/'.$filename); |
|
822 | 1 | } catch (\Exception $e) { |
|
823 | 1 | // エラーが発生しても無視する |
|
824 | } |
||
825 | 1 | $Image->setFileName($filename); |
|
826 | |||
827 | 1 | $this->entityManager->persist($Image); |
|
828 | } |
||
829 | 1 | $Tags = $CopyProduct->getProductTag(); |
|
830 | foreach ($Tags as $Tag) { |
||
831 | 1 | $this->entityManager->persist($Tag); |
|
832 | } |
||
833 | |||
834 | $this->entityManager->persist($CopyProduct); |
||
835 | |||
836 | $this->entityManager->flush(); |
||
837 | |||
838 | $event = new EventArgs( |
||
839 | [ |
||
840 | 'Product' => $Product, |
||
841 | 'CopyProduct' => $CopyProduct, |
||
842 | 'CopyProductCategories' => $CopyProductCategories, |
||
843 | 'CopyProductClasses' => $CopyProductClasses, |
||
844 | 'images' => $Images, |
||
845 | 'Tags' => $Tags, |
||
846 | ], |
||
847 | $request |
||
848 | ); |
||
849 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_COPY_COMPLETE, $event); |
||
850 | |||
851 | $this->addSuccess('admin.product.copy_complete', 'admin'); |
||
852 | |||
853 | return $this->redirectToRoute('admin_product_product_edit', ['id' => $CopyProduct->getId()]); |
||
854 | } else { |
||
855 | $this->addError('admin.product.copy_error', 'admin'); |
||
856 | } |
||
857 | } else { |
||
858 | $msg = trans('admin.product.copy_error'); |
||
859 | $this->addError($msg, 'admin'); |
||
860 | } |
||
861 | |||
862 | return $this->redirectToRoute('admin_product'); |
||
863 | } |
||
864 | |||
865 | /** |
||
866 | * @Route("/%eccube_admin_route%/product/product/{id}/display", requirements={"id" = "\d+"}, name="admin_product_product_display") |
||
867 | */ |
||
868 | public function display(Request $request, $id = null) |
||
869 | { |
||
870 | $event = new EventArgs( |
||
871 | [], |
||
872 | $request |
||
873 | ); |
||
874 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_DISPLAY_COMPLETE, $event); |
||
875 | |||
876 | if (!is_null($id)) { |
||
877 | return $this->redirectToRoute('product_detail', ['id' => $id, 'admin' => '1']); |
||
878 | } |
||
879 | |||
880 | return $this->redirectToRoute('admin_product'); |
||
881 | } |
||
882 | |||
883 | /** |
||
884 | * 商品CSVの出力. |
||
885 | * |
||
886 | * @Route("/%eccube_admin_route%/product/export", name="admin_product_export") |
||
887 | * |
||
888 | * @param Request $request |
||
889 | * |
||
890 | * @return StreamedResponse |
||
891 | */ |
||
892 | public function export(Request $request) |
||
893 | { |
||
894 | // タイムアウトを無効にする. |
||
895 | set_time_limit(0); |
||
896 | |||
897 | // sql loggerを無効にする. |
||
898 | $em = $this->entityManager; |
||
899 | $em->getConfiguration()->setSQLLogger(null); |
||
900 | |||
901 | $response = new StreamedResponse(); |
||
902 | $response->setCallback(function () use ($request) { |
||
903 | // CSV種別を元に初期化. |
||
904 | $this->csvExportService->initCsvType(CsvType::CSV_TYPE_PRODUCT); |
||
905 | |||
906 | // ヘッダ行の出力. |
||
907 | $this->csvExportService->exportHeader(); |
||
908 | |||
909 | // 商品データ検索用のクエリビルダを取得. |
||
910 | $qb = $this->csvExportService |
||
911 | ->getProductQueryBuilder($request); |
||
912 | |||
913 | // Get stock status |
||
914 | $isOutOfStock = 0; |
||
915 | $session = $request->getSession(); |
||
916 | if ($session->has('eccube.admin.product.search')) { |
||
917 | $searchData = $session->get('eccube.admin.product.search', []); |
||
918 | if (isset($searchData['stock_status']) && $searchData['stock_status'] === 0) { |
||
919 | $isOutOfStock = 1; |
||
920 | } |
||
921 | } |
||
922 | |||
923 | // joinする場合はiterateが使えないため, select句をdistinctする. |
||
924 | // http://qiita.com/suin/items/2b1e98105fa3ef89beb7 |
||
925 | // distinctのmysqlとpgsqlの挙動をあわせる. |
||
926 | // http://uedatakeshi.blogspot.jp/2010/04/distinct-oeder-by-postgresmysql.html |
||
927 | $qb->resetDQLPart('select') |
||
928 | ->resetDQLPart('orderBy') |
||
929 | ->orderBy('p.update_date', 'DESC'); |
||
930 | |||
931 | if ($isOutOfStock) { |
||
932 | $qb->select('p, pc') |
||
933 | ->distinct(); |
||
934 | } else { |
||
935 | $qb->select('p') |
||
936 | ->distinct(); |
||
937 | } |
||
938 | // データ行の出力. |
||
939 | $this->csvExportService->setExportQueryBuilder($qb); |
||
940 | |||
941 | $this->csvExportService->exportData(function ($entity, CsvExportService $csvService) use ($request) { |
||
942 | $Csvs = $csvService->getCsvs(); |
||
943 | |||
944 | /** @var $Product \Eccube\Entity\Product */ |
||
945 | $Product = $entity; |
||
946 | |||
947 | /** @var $ProductClasses \Eccube\Entity\ProductClass[] */ |
||
948 | $ProductClasses = $Product->getProductClasses(); |
||
949 | |||
950 | foreach ($ProductClasses as $ProductClass) { |
||
951 | $ExportCsvRow = new ExportCsvRow(); |
||
952 | |||
953 | // CSV出力項目と合致するデータを取得. |
||
954 | foreach ($Csvs as $Csv) { |
||
955 | // 商品データを検索. |
||
956 | $ExportCsvRow->setData($csvService->getData($Csv, $Product)); |
||
957 | if ($ExportCsvRow->isDataNull()) { |
||
958 | // 商品規格情報を検索. |
||
959 | $ExportCsvRow->setData($csvService->getData($Csv, $ProductClass)); |
||
960 | } |
||
961 | |||
962 | $event = new EventArgs( |
||
963 | [ |
||
964 | 'csvService' => $csvService, |
||
965 | 'Csv' => $Csv, |
||
966 | 'ProductClass' => $ProductClass, |
||
967 | 'ExportCsvRow' => $ExportCsvRow, |
||
968 | ], |
||
969 | $request |
||
970 | ); |
||
971 | $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_PRODUCT_CSV_EXPORT, $event); |
||
972 | |||
973 | $ExportCsvRow->pushData(); |
||
974 | } |
||
975 | |||
976 | // $row[] = number_format(memory_get_usage(true)); |
||
977 | // 出力. |
||
978 | $csvService->fputcsv($ExportCsvRow->getRow()); |
||
979 | } |
||
980 | }); |
||
981 | }); |
||
982 | |||
983 | $now = new \DateTime(); |
||
984 | $filename = 'product_'.$now->format('YmdHis').'.csv'; |
||
985 | $response->headers->set('Content-Type', 'application/octet-stream'); |
||
986 | $response->headers->set('Content-Disposition', 'attachment; filename='.$filename); |
||
987 | $response->send(); |
||
988 | |||
989 | log_info('商品CSV出力ファイル名', [$filename]); |
||
990 | |||
991 | return $response; |
||
992 | } |
||
993 | |||
994 | /** |
||
995 | * ProductCategory作成 |
||
996 | * |
||
997 | * @param \Eccube\Entity\Product $Product |
||
998 | * @param \Eccube\Entity\Category $Category |
||
999 | * @param integer $count |
||
1000 | * |
||
1001 | * @return \Eccube\Entity\ProductCategory |
||
1002 | */ |
||
1003 | View Code Duplication | private function createProductCategory($Product, $Category, $count) |
|
0 ignored issues
–
show
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...
|
|||
1004 | 1 | { |
|
1005 | $ProductCategory = new ProductCategory(); |
||
1006 | 1 | $ProductCategory->setProduct($Product); |
|
1007 | $ProductCategory->setProductId($Product->getId()); |
||
1008 | $ProductCategory->setCategory($Category); |
||
1009 | 1 | $ProductCategory->setCategoryId($Category->getId()); |
|
1010 | 1 | ||
1011 | 1 | return $ProductCategory; |
|
1012 | } |
||
1013 | 1 | ||
1014 | 1 | /** |
|
1015 | 1 | * Bulk public action |
|
1016 | * |
||
1017 | 1 | * @Route("/%eccube_admin_route%/product/bulk/product-status/{id}", requirements={"id" = "\d+"}, name="admin_product_bulk_product_status", methods={"POST"}) |
|
1018 | * |
||
1019 | * @param Request $request |
||
1020 | * @param ProductStatus $ProductStatus |
||
1021 | 1 | * |
|
1022 | 1 | * @return RedirectResponse |
|
1023 | 1 | */ |
|
1024 | 1 | public function bulkProductStatus(Request $request, ProductStatus $ProductStatus, CacheUtil $cacheUtil) |
|
1025 | 1 | { |
|
1026 | $this->isTokenValid(); |
||
1027 | 1 | ||
1028 | /** @var Product[] $Products */ |
||
1029 | $Products = $this->productRepository->findBy(['id' => $request->get('ids')]); |
||
1030 | $count = 0; |
||
1031 | foreach ($Products as $Product) { |
||
1032 | try { |
||
1033 | 1 | $Product->setStatus($ProductStatus); |
|
1034 | $this->productRepository->save($Product); |
||
1035 | $count++; |
||
1036 | } catch (\Exception $e) { |
||
1037 | $this->addError($e->getMessage(), 'admin'); |
||
1038 | } |
||
1039 | } |
||
1040 | try { |
||
1041 | if ($count) { |
||
1042 | $this->entityManager->flush(); |
||
1043 | $msg = $this->translator->trans('admin.product.bulk_change_status_complete', [ |
||
1044 | '%count%' => $count, |
||
1045 | '%status%' => $ProductStatus->getName(), |
||
1046 | ]); |
||
1047 | $this->addSuccess($msg, 'admin'); |
||
1048 | $cacheUtil->clearDoctrineCache(); |
||
1049 | } |
||
1050 | } catch (\Exception $e) { |
||
1051 | $this->addError($e->getMessage(), 'admin'); |
||
1052 | } |
||
1053 | |||
1054 | return $this->redirectToRoute('admin_product', ['resume' => Constant::ENABLED]); |
||
1055 | } |
||
1056 | } |
||
1057 |
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.