Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 40 | class OrderHelper |
||
| 41 | { |
||
| 42 | // FIXME 必要なメソッドのみ移植する |
||
| 43 | use ControllerTrait; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @var ContainerInterface |
||
| 47 | */ |
||
| 48 | protected $container; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @var string 非会員情報を保持するセッションのキー |
||
| 52 | */ |
||
| 53 | const SESSION_NON_MEMBER = 'eccube.front.shopping.nonmember'; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var string 非会員の住所情報を保持するセッションのキー |
||
| 57 | */ |
||
| 58 | const SESSION_NON_MEMBER_ADDRESSES = 'eccube.front.shopping.nonmember.customeraddress'; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @var string 受注IDを保持するセッションのキー |
||
| 62 | */ |
||
| 63 | const SESSION_ORDER_ID = 'eccube.front.shopping.order.id'; |
||
| 64 | |||
| 65 | /** |
||
| 66 | * @var string カートが分割されているかどうかのフラグ. 購入フローからのログイン時にカートが分割された場合にtrueがセットされる. |
||
| 67 | * |
||
| 68 | * @see SecurityListener |
||
| 69 | */ |
||
| 70 | const SESSION_CART_DEVIDE_FLAG = 'eccube.front.cart.divide'; |
||
| 71 | |||
| 72 | /** |
||
| 73 | * @var SessionInterface |
||
| 74 | */ |
||
| 75 | protected $session; |
||
| 76 | |||
| 77 | /** |
||
| 78 | * @var PrefRepository |
||
| 79 | */ |
||
| 80 | protected $prefRepository; |
||
| 81 | |||
| 82 | /** |
||
| 83 | * @var OrderRepository |
||
| 84 | */ |
||
| 85 | protected $orderRepository; |
||
| 86 | |||
| 87 | /** |
||
| 88 | * @var OrderItemTypeRepository |
||
| 89 | */ |
||
| 90 | protected $orderItemTypeRepository; |
||
| 91 | |||
| 92 | public function __construct( |
||
| 93 | ContainerInterface $container, |
||
| 94 | EntityManagerInterface $entityManager, |
||
| 95 | OrderRepository $orderRepository, |
||
| 96 | OrderItemTypeRepository $orderItemTypeRepository, |
||
| 97 | OrderStatusRepository $orderStatusRepository, |
||
| 98 | DeliveryRepository $deliveryRepository, |
||
| 99 | PaymentRepository $paymentRepository, |
||
| 100 | DeviceTypeRepository $deviceTypeRepository, |
||
| 101 | PrefRepository $prefRepository, |
||
| 102 | MobileDetector $mobileDetector, |
||
| 103 | SessionInterface $session |
||
| 104 | ) { |
||
| 105 | $this->container = $container; |
||
| 106 | $this->orderRepository = $orderRepository; |
||
| 107 | $this->orderStatusRepository = $orderStatusRepository; |
||
| 108 | $this->orderItemTypeRepository = $orderItemTypeRepository; |
||
| 109 | $this->deliveryRepository = $deliveryRepository; |
||
| 110 | $this->paymentRepository = $paymentRepository; |
||
| 111 | $this->deviceTypeRepository = $deviceTypeRepository; |
||
| 112 | $this->entityManager = $entityManager; |
||
| 113 | $this->prefRepository = $prefRepository; |
||
| 114 | $this->mobileDetector = $mobileDetector; |
||
| 115 | 175 | $this->session = $session; |
|
| 116 | } |
||
| 117 | |||
| 118 | /** |
||
| 119 | * 購入処理中の受注を生成する. |
||
| 120 | * |
||
| 121 | * @param Customer $Customer |
||
| 122 | * @param $CartItems |
||
| 123 | * |
||
| 124 | * @return Order |
||
| 125 | */ |
||
| 126 | public function createPurchaseProcessingOrder(Cart $Cart, Customer $Customer) |
||
| 127 | { |
||
| 128 | 175 | $OrderStatus = $this->orderStatusRepository->find(OrderStatus::PROCESSING); |
|
| 129 | 175 | $Order = new Order($OrderStatus); |
|
| 130 | 175 | ||
| 131 | 175 | $preOrderId = $this->createPreOrderId(); |
|
| 132 | 175 | $Order->setPreOrderId($preOrderId); |
|
| 133 | 175 | ||
| 134 | 175 | // 顧客情報の設定 |
|
| 135 | 175 | $this->setCustomer($Order, $Customer); |
|
| 136 | 175 | ||
| 137 | 175 | $DeviceType = $this->deviceTypeRepository->find($this->mobileDetector->isMobile() ? DeviceType::DEVICE_TYPE_MB : DeviceType::DEVICE_TYPE_PC); |
|
| 138 | 175 | $Order->setDeviceType($DeviceType); |
|
| 139 | |||
| 140 | // 明細情報の設定 |
||
| 141 | $OrderItems = $this->createOrderItemsFromCartItems($Cart->getCartItems()); |
||
|
|
|||
| 142 | $OrderItemsGroupBySaleType = array_reduce($OrderItems, function ($result, $item) { |
||
| 143 | /* @var OrderItem $item */ |
||
| 144 | $saleTypeId = $item->getProductClass()->getSaleType()->getId(); |
||
| 145 | $result[$saleTypeId][] = $item; |
||
| 146 | |||
| 147 | return $result; |
||
| 148 | }, []); |
||
| 149 | 51 | ||
| 150 | foreach ($OrderItemsGroupBySaleType as $OrderItems) { |
||
| 151 | 51 | $Shipping = $this->createShippingFromCustomer($Customer); |
|
| 152 | 51 | $Shipping->setOrder($Order); |
|
| 153 | $this->addOrderItems($Order, $Shipping, $OrderItems); |
||
| 154 | 51 | $this->setDefaultDelivery($Shipping); |
|
| 155 | $this->entityManager->persist($Shipping); |
||
| 156 | 51 | $Order->addShipping($Shipping); |
|
| 157 | } |
||
| 158 | |||
| 159 | $this->setDefaultPayment($Order); |
||
| 160 | 51 | ||
| 161 | $this->entityManager->persist($Order); |
||
| 162 | 51 | ||
| 163 | 51 | return $Order; |
|
| 164 | } |
||
| 165 | |||
| 166 | 51 | /** |
|
| 167 | 51 | * @param Cart|null $Cart |
|
| 168 | * @return bool |
||
| 169 | 51 | */ |
|
| 170 | 51 | public function verifyCart(Cart $Cart = null) |
|
| 171 | { |
||
| 172 | 51 | if ($Cart && count($Cart->getCartItems()) > 0) { |
|
| 173 | 51 | $divide = $this->session->get(self::SESSION_CART_DEVIDE_FLAG); |
|
| 174 | if ($divide) { |
||
| 175 | 51 | log_info('ログイン時に販売種別が異なる商品がカートと結合されました。'); |
|
| 176 | 51 | ||
| 177 | 51 | return false; |
|
| 178 | 51 | } |
|
| 179 | 51 | ||
| 180 | 51 | return true; |
|
| 181 | 51 | } |
|
| 182 | |||
| 183 | log_info('カートに商品が入っていません。'); |
||
| 184 | 51 | ||
| 185 | return false; |
||
| 186 | 51 | } |
|
| 187 | |||
| 188 | /** |
||
| 189 | 51 | * 注文手続き画面でログインが必要かどうかの判定 |
|
| 190 | * |
||
| 191 | * @return bool |
||
| 192 | */ |
||
| 193 | public function isLoginRequired() |
||
| 194 | { |
||
| 195 | // フォームログイン済はログイン不要 |
||
| 196 | if ($this->isGranted('IS_AUTHENTICATED_FULLY')) { |
||
| 197 | return false; |
||
| 198 | } |
||
| 199 | 2 | ||
| 200 | // Remember Meログイン済の場合はフォームからのログインが必要 |
||
| 201 | 2 | if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) { |
|
| 202 | 2 | return true; |
|
| 203 | } |
||
| 204 | 2 | ||
| 205 | 1 | // 未ログインだがお客様情報を入力している場合はログイン不要 |
|
| 206 | 1 | if (!$this->getUser() && $this->getNonMember()) { |
|
| 207 | 1 | return false; |
|
| 208 | 1 | } |
|
| 209 | 1 | ||
| 210 | 1 | return true; |
|
| 211 | 1 | } |
|
| 212 | |||
| 213 | /** |
||
| 214 | 2 | * 購入処理中の受注を取得する. |
|
| 215 | * |
||
| 216 | * @param null|string $preOrderId |
||
| 217 | 51 | * |
|
| 218 | * @return null|Order |
||
| 219 | */ |
||
| 220 | public function getPurchaseProcessingOrder($preOrderId = null) |
||
| 221 | 51 | { |
|
| 222 | if (null === $preOrderId) { |
||
| 223 | 51 | return null; |
|
| 224 | } |
||
| 225 | 51 | ||
| 226 | return $this->orderRepository->findOneBy([ |
||
| 227 | 'pre_order_id' => $preOrderId, |
||
| 228 | 'OrderStatus' => OrderStatus::PROCESSING, |
||
| 229 | 51 | ]); |
|
| 230 | } |
||
| 231 | 51 | ||
| 232 | /** |
||
| 233 | * セッションに保持されている非会員情報を取得する. |
||
| 234 | 51 | * 非会員購入時に入力されたお客様情報を返す. |
|
| 235 | * |
||
| 236 | 51 | * @return Customer |
|
| 237 | 34 | */ |
|
| 238 | View Code Duplication | public function getNonMember() |
|
| 239 | { |
||
| 240 | 51 | $NonMember = $this->session->get(self::SESSION_NON_MEMBER); |
|
| 241 | 51 | if ($NonMember && $NonMember->getPref()) { |
|
| 242 | $Pref = $this->prefRepository->find($NonMember->getPref()->getId()); |
||
| 243 | 51 | $NonMember->setPref($Pref); |
|
| 244 | } |
||
| 245 | |||
| 246 | return $NonMember; |
||
| 247 | } |
||
| 248 | |||
| 249 | /** |
||
| 250 | * @param Cart $Cart |
||
| 251 | * @param Customer $Customer |
||
| 252 | * |
||
| 253 | * @return Order|null |
||
| 254 | */ |
||
| 255 | public function initializeOrder(Cart $Cart, Customer $Customer) |
||
| 256 | 51 | { |
|
| 257 | // 購入処理中の受注情報を取得 |
||
| 258 | 51 | if ($Order = $this->getPurchaseProcessingOrder($Cart->getPreOrderId())) { |
|
| 259 | return $Order; |
||
| 260 | 51 | } |
|
| 261 | |||
| 262 | // 受注情報を作成 |
||
| 263 | 51 | $Order = $this->createPurchaseProcessingOrder($Cart, $Customer); |
|
| 264 | $Cart->setPreOrderId($Order->getPreOrderId()); |
||
| 265 | 51 | ||
| 266 | return $Order; |
||
| 267 | 51 | } |
|
| 268 | |||
| 269 | 51 | public function removeSession() |
|
| 270 | 51 | { |
|
| 271 | 51 | $this->session->remove(self::SESSION_ORDER_ID); |
|
| 272 | 51 | $this->session->remove(self::SESSION_ORDER_ID); |
|
| 273 | 51 | $this->session->remove(self::SESSION_NON_MEMBER); |
|
| 274 | 51 | $this->session->remove(self::SESSION_NON_MEMBER_ADDRESSES); |
|
| 275 | 51 | } |
|
| 276 | |||
| 277 | 51 | private function createPreOrderId() |
|
| 278 | 51 | { |
|
| 279 | 51 | // ランダムなpre_order_idを作成 |
|
| 280 | 51 | do { |
|
| 281 | $preOrderId = sha1(StringUtil::random(32)); |
||
| 282 | 51 | ||
| 283 | 51 | $Order = $this->orderRepository->findOneBy( |
|
| 284 | 42 | [ |
|
| 285 | 42 | 'pre_order_id' => $preOrderId, |
|
| 286 | 'OrderStatus' => OrderStatus::PROCESSING, |
||
| 287 | ] |
||
| 288 | 51 | ); |
|
| 289 | 51 | } while ($Order); |
|
| 290 | |||
| 291 | return $preOrderId; |
||
| 292 | 51 | } |
|
| 293 | |||
| 294 | 51 | private function setCustomer(Order $Order, Customer $Customer) |
|
| 295 | { |
||
| 296 | 51 | if ($Customer->getId()) { |
|
| 297 | 51 | $Order->setCustomer($Customer); |
|
| 298 | 51 | } |
|
| 299 | 51 | ||
| 300 | 51 | $Order->copyProperties( |
|
| 301 | 51 | $Customer, |
|
| 302 | 51 | [ |
|
| 303 | 51 | 'id', |
|
| 304 | 51 | 'create_date', |
|
| 305 | 51 | 'update_date', |
|
| 306 | 'del_flg', |
||
| 307 | 51 | ] |
|
| 308 | ); |
||
| 309 | } |
||
| 310 | 51 | ||
| 311 | /** |
||
| 312 | * @param ArrayCollection|CartItem[] $CartItems |
||
| 313 | 51 | * |
|
| 314 | 51 | * @return OrderItem[] |
|
| 315 | */ |
||
| 316 | 51 | private function createOrderItemsFromCartItems($CartItems) |
|
| 317 | 51 | { |
|
| 318 | 51 | $ProductItemType = $this->orderItemTypeRepository->find(OrderItemType::PRODUCT); |
|
| 319 | 51 | ||
| 320 | return array_map(function ($item) use ($ProductItemType) { |
||
| 321 | /* @var $item CartItem */ |
||
| 322 | /* @var $ProductClass \Eccube\Entity\ProductClass */ |
||
| 323 | 51 | $ProductClass = $item->getProductClass(); |
|
| 324 | /* @var $Product \Eccube\Entity\Product */ |
||
| 325 | $Product = $ProductClass->getProduct(); |
||
| 326 | 51 | ||
| 327 | 51 | $OrderItem = new OrderItem(); |
|
| 328 | 51 | $OrderItem |
|
| 329 | ->setProduct($Product) |
||
| 330 | ->setProductClass($ProductClass) |
||
| 331 | 51 | ->setProductName($Product->getName()) |
|
| 332 | ->setProductCode($ProductClass->getCode()) |
||
| 333 | 51 | ->setPrice($ProductClass->getPrice02()) |
|
| 334 | ->setQuantity($item->getQuantity()) |
||
| 335 | ->setOrderItemType($ProductItemType); |
||
| 336 | 51 | ||
| 337 | $ClassCategory1 = $ProductClass->getClassCategory1(); |
||
| 338 | 51 | if (!is_null($ClassCategory1)) { |
|
| 339 | 51 | $OrderItem->setClasscategoryName1($ClassCategory1->getName()); |
|
| 340 | 51 | $OrderItem->setClassName1($ClassCategory1->getClassName()->getName()); |
|
| 341 | } |
||
| 342 | $ClassCategory2 = $ProductClass->getClassCategory2(); |
||
| 343 | if (!is_null($ClassCategory2)) { |
||
| 344 | 51 | $OrderItem->setClasscategoryName2($ClassCategory2->getName()); |
|
| 345 | 51 | $OrderItem->setClassName2($ClassCategory2->getClassName()->getName()); |
|
| 346 | } |
||
| 347 | |||
| 348 | return $OrderItem; |
||
| 349 | 51 | }, $CartItems->toArray()); |
|
| 350 | } |
||
| 351 | |||
| 352 | 51 | /** |
|
| 353 | * @param Customer $Customer |
||
| 354 | * |
||
| 355 | 51 | * @return Shipping |
|
| 356 | 51 | */ |
|
| 357 | 51 | private function createShippingFromCustomer(Customer $Customer) |
|
| 374 | |||
| 375 | /** |
||
| 376 | * @param Shipping $Shipping |
||
| 377 | */ |
||
| 378 | private function setDefaultDelivery(Shipping $Shipping) |
||
| 398 | |||
| 399 | /** |
||
| 400 | * @param Order $Order |
||
| 401 | */ |
||
| 402 | private function setDefaultPayment(Order $Order) |
||
| 432 | |||
| 433 | /** |
||
| 434 | * @param Order $Order |
||
| 435 | * @param Shipping $Shipping |
||
| 436 | * @param array $OrderItems |
||
| 437 | */ |
||
| 438 | private function addOrderItems(Order $Order, Shipping $Shipping, array $OrderItems) |
||
| 447 | } |
||
| 448 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.