setTable( new FeesTable()); } /** * * set fees array * * @param array $fees * * @return $this */ public function setFees($fees) { $this->_fees = $fees; return $this; } /** * * get fees array or the name of a certain fee if key is specified * * @param string $key * * @return array|string */ public function getFees($key = null) { if (array_key_exists($key, $this->_fees)) { return $this->_fees[$key]; } return $this->_fees; } /** * * get fees tiers array * * @return array */ public function getFeesTiers() { return $this->_feesTiers; } /** * * set fees tiers array * * @param array $feesTiers * * @return $this */ public function setFeesTiers($feesTiers) { $this->_feesTiers = $feesTiers; return $this; } /** * * check if a fee has tiers * * @param string|null $feeName * * @return bool */ public function hasTiers($feeName = null) { if ($feeName === null) { $feeName = $this->_feeName; } return (in_array($feeName, $this->_feesTiers)); } /** * * get fees with no category array * * @return array */ public function getFeesNoCategory() { return $this->_feesNoCategory; } /** * * set fees with no category array * * @param array $feesNoCategory * * @return $this */ public function setFeesNoCategory($feesNoCategory) { $this->_feesNoCategory = $feesNoCategory; return $this; } /** * * check if a fee has no categories option * * @param string|null $feeName * * @return bool */ public function hasNoCategory($feeName = null) { if ($feeName === null) { $feeName = $this->_feeName; } return (in_array($feeName, $this->_feesNoCategory)); } /** * * get fee name * * @return string * @throws \RuntimeException */ public function getFeeName() { if ($this->_feeName === null) { throw new \RuntimeException( "A fee name is required when querying the fees table."); } return $this->_feeName; } /** * * set the fee name * * @param string $feeName * * @return $this */ public function setFeeName($feeName) { $this->_feeName = $feeName; return $this; } /** * * set user data * * @param int|string|\Ppb\Db\Table\Row\User $user * * @return $this * @throws \InvalidArgumentException */ public function setUser($user) { if (is_int($user) || is_string($user)) { $userService = new Service\Users(); $user = $userService->findBy('id', $user); } if (!$user instanceof User) { throw new \InvalidArgumentException("The method requires a string, an integer or an object of type \Ppb\Db\Table\Row\User."); } $this->_user = $user; return $this; } /** * * get calculation amount * * @return float */ public function getAmount() { return $this->_amount; } /** * * set calculation amount * * @param float $amount * * @return $this */ public function setAmount($amount) { $this->_amount = $amount; return $this; } /** * * get currency for the amount for which the fee is to be calculated * * @return string */ public function getCurrency() { return $this->_currency; } /** * * set currency for the amount for which the fee is to be calculated * * @param string $currency * * @return $this */ public function setCurrency($currency) { $this->_currency = $currency; return $this; } /** * * get category id * * @return int */ public function getCategoryId() { return $this->_categoryId; } /** * * set fee category id, but only if custom fees are enabled * * @param int $categoryId * * @return $this */ public function setCategoryId($categoryId) { if ($categoryId > 0) { $categories = new Service\Table\Relational\Categories(); $mainCategory = $categories->getRoot($categoryId); if ($mainCategory instanceof Category) { $categoryId = ($mainCategory->getData('custom_fees')) ? $mainCategory->getData('id') : null; } else { $categoryId = null; } } $this->_categoryId = $categoryId; return $this; } /** * * get currencies table service * * @return \Ppb\Service\Table\Currencies */ public function getCurrencies() { if (!$this->_currencies instanceof Service\Table\Currencies) { $this->setCurrencies( new Service\Table\Currencies()); } return $this->_currencies; } /** * * set currencies service * * @param \Ppb\Service\Table\Currencies $currencies * * @return $this */ public function setCurrencies(Service\Table\Currencies $currencies) { $this->_currencies = $currencies; return $this; } /** * * get fees calculation flag * * @return bool */ public function isDisabledFees() { return $this->_disableFees; } /** * * set fees calculation flag * * @param bool $disableFees * * @return $this */ public function disableFees($disableFees = true) { $this->_disableFees = (bool)$disableFees; return $this; } /** * * set tax type object * * @param \Ppb\Db\Table\Row\TaxType $taxType * * @return $this */ public function setTaxType(TaxType $taxType) { $this->_taxType = $taxType; return $this; } /** * * get tax type object * * @return \Ppb\Db\Table\Row\TaxType */ public function getTaxType() { if (!$this->_taxType instanceof TaxType) { $settings = $this->getSettings(); $this->setTaxType( new TaxType(array( 'table' => new \Ppb\Db\Table\TaxTypes(), 'data' => array() ))); if ($settings['enable_tax_fees'] && $settings['tax_fees_type']) { $taxTypesService = new Service\Table\TaxTypes(); $taxType = $taxTypesService->findBy('id', $settings['tax_fees_type']); if ($taxType instanceof TaxType) { $locationsIds = \Ppb\Utility::unserialize($taxType->getData('locations_ids')); $address = $this->getUser()->getAddress(); if (isset($address['country']) && isset($address['state']) && is_array($locationsIds)) { if (in_array($address['country'], $locationsIds) || in_array($address['state'], $locationsIds)) { $this->setTaxType($taxType); } } } } } return $this->_taxType; } /** * * set voucher object * * @param string|\Ppb\Db\Table\Row\Voucher $voucher voucher code or voucher object * * @return $this */ public function setVoucher($voucher) { if (!$voucher instanceof Voucher) { $vouchersService = new Service\Vouchers(); $voucher = $vouchersService->findBy($voucher); } $this->_voucher = $voucher; return $this; } /** * * get voucher object * * @return \Ppb\Db\Table\Row\Voucher */ public function getVoucher() { return $this->_voucher; } /** * * set redirect params * * @param array|string $redirect * * @return $this */ public function setRedirect($redirect) { $this->_redirect = $redirect; return $this; } /** * * get redirect params * * @return array|string */ public function getRedirect() { return $this->_redirect; } /** * * set listing type * * @param string $type * * @return $this */ public function setType($type) { $this->_type = $type; return $this; } /** * * get listing type * * @return string */ public function getType() { return $this->_type; } /** * * get transaction details * * @return mixed */ public function getTransactionDetails() { return $this->_transactionDetails; } /** * * set transaction details * * @param mixed $transactionDetails * * @return $this */ public function setTransactionDetails($transactionDetails) { $this->_transactionDetails = $transactionDetails; return $this; } /** * * get the amount of a certain fee * calculates based on preferred seller feature * * @param string $name * @param float $amount * @param int $categoryId * @param null $currency * * @return float|null return the fee amount or null if no fee applies for the selected action */ public function getFeeAmount($name = null, $amount = null, $categoryId = null, $currency = null) { if ($this->isDisabledFees()) { return null; } if ($name === null) { $name = $this->getFeeName(); } if ($amount === null) { $amount = $this->getAmount(); } if ($categoryId !== null) { $this->setCategoryId($categoryId); } $categoryId = $this->getCategoryId(); if ($currency !== null) { $this->setCurrency($currency); } $currency = $this->getCurrency(); $select = $this->_table->select(array('amount', 'calculation_type')) ->where("name = ?", $name) ->where("type = ?", $this->getType()); if (in_array($name, $this->_feesTiers) && $amount !== null) { $amountConverted = $this->getCurrencies()->convertAmount($amount, $currency); $select->where("tier_from < ?", $amountConverted) ->where("tier_to >= ?", $amountConverted); } if ($categoryId !== null) { $select->where("category_id = ?", $categoryId); } else { $select->where("category_id IS NULL"); } $row = $this->_table->fetchRow($select); if ($row !== null) { if ($row['calculation_type'] == 'percent') { $amount = $row['amount'] * $amount / 100; $amount = $this->getCurrencies()->convertAmount($amount, $currency); } else { $amount = $row['amount']; } if (!in_array($name, $this->_additionalConstants)) { $amount = $this->_applyPreferredSellersReduction($amount); $amount = $this->_addTax($amount); } return $amount; // return $this->_applyVoucher($amount, $settings['currency']); } return null; } /** * * save data in the fees table * * @param array $data * * @return $this */ public function save(array $data) { $categoryId = null; $calculationType = 'flat'; $type = 'default'; $feeName = $this->getFeeName(); if (isset($data['category_id'])) { $categoryId = intval($data['category_id']); unset($data['category_id']); } if (isset($data['calculation_type'])) { if (!is_array($data['calculation_type'])) { $calculationType = $data['calculation_type']; unset($data['calculation_type']); } } if (isset($data['sale_fee_payer'])) { $settingsService = new Settings(); $settingsService->save(array( 'sale_fee_payer' => $data['sale_fee_payer'], )); } if (isset($data['type'])) { $type = $data['type']; unset($data['type']); } $table = $this->getTable(); if ($this->hasTiers()) { if (isset($data['tier_from'])) { foreach ($data['tier_from'] as $key => $tierFrom) { if (!empty($data['amount'][$key])) { $row = $where = null; if (!empty($data['id'][$key])) { $where = $table->getAdapter()->quoteInto('id = ?', intval($data['id'][$key])); $row = $this->getTable()->fetchRow($where); } $array = array( 'name' => $feeName, 'type' => $type, 'amount' => $data['amount'][$key], 'calculation_type' => $data['calculation_type'][$key], 'category_id' => (!empty($categoryId)) ? $categoryId : new Expr('null'), 'tier_from' => $data['tier_from'][$key], 'tier_to' => $data['tier_to'][$key], ); if (count($row) > 0) { $table->update($array, $where); } else { $table->insert($array); } } } } } else { foreach ($data as $key => $value) { $where = $table->select() ->where('name = ?', $key) ->where('type = ?', $type); if ($categoryId) { $where->where('category_id = ?', $categoryId); } else { $where->where('category_id IS NULL'); } $row = $table->fetchRow($where); $insert = array( 'amount' => $value, 'calculation_type' => $calculationType); if (count($row) > 0) { $table->update($insert, "id = '{$row['id']}'"); } else { $insert['name'] = $key; if (isset($type)) { $insert['type'] = $type; } if ($categoryId) { $insert['category_id'] = $categoryId; } $table->insert($insert); } } } return $this; } /** * * get fees data for usage in admin setup forms * * @param string $name the name of the fee * @param integer $categoryId id of the category * @param string $type fee/listing type * * @return array */ public function getData($name = null, $categoryId = null, $type = null) { if ($name === null) { $name = $this->getFeeName(); } if ($type !== null) { $this->setType($type); } $type = $this->getType(); $select = $this->_table->select() ->where('type = ?', $type); if ($name !== null) { $select->where("name = ?", $name); } if ($categoryId) { $select->where("category_id = ?", $categoryId); } else { $select->where("category_id IS NULL"); } $data = $this->fetchAll($select)->toArray(); // if data = 1 then get all non tiered fields plus a 'type' field if ($this->hasTiers() !== true) { $result['fee_type'] = (isset($data[0]['calculation_type'])) ? $data[0]['calculation_type'] : self::DEFAULT_CALCULATION_TYPE; $select = $this->_table->select() ->where('type = ?', $type); if ($categoryId) { $select->where("category_id = ?", $categoryId); } else { $select->where("category_id IS NULL"); } $rows = $this->fetchAll($select); foreach ($rows as $row) { $result[$row['name']] = $row['amount']; } $data = $result; } $data['category_id'] = $categoryId; return $data; } /** * * delete table data by id - fees tiers only * * @param array $data * * @return int The number of affected rows. */ public function delete(array $data) { $data = array_filter( array_values($data)); if (count($data) > 0) { return $this->_table->delete("id IN (" . implode(',', $data) . ")"); } return null; } /** * * add tax to a certain value, and return the rounded value * * @param float $value * * @return float */ protected function _addTax($value) { $value += $value * $this->getTaxType()->getData('amount') / 100; return $this->_roundNumber($value); } /** * * apply voucher to a certain value and currency and return rounded value * * @param float $value * @param string $currency * * @return float */ protected function _applyVoucher($value, $currency) { if (($voucher = $this->getVoucher()) instanceof Voucher) { $value = $voucher->apply($value, $currency); } return $this->_roundNumber($value); } /** * * apply preferred sellers reduction, and return rounded value * * @param $value * * @return float */ protected function _applyPreferredSellersReduction($value) { $settings = $this->getSettings(); if ($settings['preferred_sellers'] && $this->_user['preferred_seller']) { $value = ($value * (1 - $settings['preferred_sellers_reduction'] / 100)); } return $this->_roundNumber($value); } /** * * requires an array of data and * makes the required modifications to the affected tables * * functionality defined in child classes * * @param bool $ipn true if payment is completed, false otherwise * @param array $post data needed by the method */ public function callback($ipn, array $post) { } /** * * get the signup fee value (tax included) * * functionality defined in child classes * * @return void */ public function getTotalAmount() { } }