setPrimaryKey($data['productId']); $this->_cartItemData = $data; return $this; } public function prepareCartItemData() { $this->_cartItemData['showDescription'] = 'y'; return $this->_cartItemData; } public function beforeValidateCart() { return $this; } public function validateCartItem() { $this->_errors = []; if (!($membership = $this->_getTable()->search($this->_cartItemData['productId']))) { $this->_errors[] = 'This Membership is not longer exists'; } if ($this->_cartItemData['quantity'] != 1) { $this->_errors[] = 'Wrong quantity.'; } return empty($this->_errors); } public function completeItemList(array $itemList) { foreach ($itemList as $cartItem) { $result = $this->renewMembership($cartItem['productId'] /* membershipId */, $cartItem['productCategoryId'] /* userId */); Mail::sendMembershipRenewedToAdmin($result); } return $this; } public function afterCartItemRemove() { return $this; } public function renew($userId) { if (!($user = $this->_getTable('User')->searchBy(['id' => $userId, 'bought' => 'y']))) { throw new Exception('Can\'t find user by id=' . (int) $userId); } if (empty($user['membershipTypeId'])) { throw new Exception('Membership is not assigned'); } if (!($membership = $this->_getTable('MembershipType')->search($user['membershipTypeId']))) { throw new Exception('Can\'t find membership by id=' . (int) $user['membershipTypeId']); } if ((float) $membership['price'] <= 0) { // If membership became free we don't need to go over shopping cart $result = $this->renewMembership($user['membershipTypeId'], $user['id']); Mail::sendMembershipRenewedToAdmin($result); return self::RENEWED; } $cartItem = [ 'cartItemType' => 'User\\MembershipType\\', 'productId' => $membership['id'], 'productCategoryId' => $user['id'], 'title' => 'Renewing Membership', 'description' => Qs_String::fill( $this->getConfig('cartItemDescription'), [ 'firstName' => $user['firstName'], 'lastName' => $user['lastName'], 'membershipType' => $membership['title'], ] ), 'applyTax' => 'n', 'tax' => 0, 'quantity' => 1, 'price' => $membership['price'], 'weight' => 0, 'applyShipping' => 'n', ]; $cart = CartObj::getInstance(); if ($cart->itemExists(Qs_Array::map($cartItem, ['cartItemType', 'productId', 'productCategoryId']))) { throw new Exception('You already have Membership item in your Shopping Cart'); } $cart->addItem($cartItem); return self::CHECKOUT_REQUIRED; } public function renewMembership($membershipId, $userId) { if (!($membership = $this->_getTable('MembershipType')->search($membershipId))) { return $this; } if (!($user = $this->_getTable('User')->search($userId))) { return $this; } $fromTime = null; // start membership period from expiredOn date if it is in the future if (!empty($user['expiredOn']) && ($user['expiredOn'] > date('Y-m-d'))) { $fromTime = strtotime($user['expiredOn']); } $expiredOn = $this->calculateMembershipExpiration($membership['duration'], $fromTime); $this->_getTable('User')->updateByKey(compact('expiredOn'), $userId); return [ 'user' => $user, 'membership' => $membership, 'newExpirationDate' => $expiredOn, ]; } public function calculateMembershipExpiration($years, $fromTime = null) { $years = (int) $years; if (empty($years)) { return null; } if (null === $fromTime) { $fromTime = time(); } $currentYear = idate('Y', $fromTime); $currentMonth = idate('m', $fromTime); // AFTER October 1st will get the last quarter of the current year for free if ($currentMonth >= 10) { $years++; } $expiredOn = mktime(0, 0, 0, 12, 31, $currentYear + $years - 1); return date('Y-m-d', $expiredOn); } }