/**
	 * Times out unused baskets according to general settings
	 *
	 * @param  int|null  $userId  Timeout for User id only (triggered by user), or if 0: triggered by admin
	 * @param  int       $limit   Maximum number of baskets to timeout this time
	 * @return int|null           Number of baskets that just timed out
	 */
	public function timeoutUnusedBaskets( $userId, $limit = 100 ) {
		global $_CB_database;

		$params		=	cbpaidApp::settingsParams();

		$query		=	"SELECT b.id FROM #__cbsubs_payment_baskets b"
			.	"\n WHERE b.payment_status = 'NotInitiated'"
			.	"\n AND b.payment_method IS NULL"
		;
		if ( $userId ) {
			$query	.=	"\n AND b.user_id = " . (int) $userId;
			$hours	=	$params->get( 'basket_timeout_user', 3 );
		} else {
			$hours	=	$params->get( 'basket_timeout_admin', 24 );
		}
		$query		.=	"\n AND b.time_initiated < DATE_SUB( NOW(), INTERVAL " . ( (int) $hours ) . " HOUR)";
		$_CB_database->setQuery( $query, 0, $limit );
		$ids		=	$_CB_database->loadResultArray();
		if ( is_array( $ids ) ) {
			foreach ( $ids as $basketId ) {
				$paymentBasket	=	new cbpaidPaymentBasket( $_CB_database );
				$paymentBasket->historySetMessage( 'Basket timeout' );
				$paymentBasket->delete( $basketId );
			}
			return count( $ids );
		} else {
			return null;
		}

	}
 /**
  * Draws the user profile tab "Subscriptions" (if enabled, user is the profile owner, and something to display.
  * 
  * @param  UserTable  $user
  * @param  boolean    $itsmyself
  * @param  string     $htmlSubscribed
  * @return string
  */
 public function drawUserSomethings($user, $itsmyself, $htmlSubscribed)
 {
     global $_CB_framework, $ueConfig;
     $this->htmlSubscribed = $htmlSubscribed;
     $subscriptions = $this->_model;
     if (count($subscriptions) == 1) {
         $subTxt = CBPTXT::T(cbpaidApp::settingsParams()->get('subscription_name', 'subscription'));
     } else {
         $subTxt = CBPTXT::T(cbpaidApp::settingsParams()->get('subscriptions_name', 'subscriptions'));
     }
     if ($itsmyself) {
         $userName = null;
     } else {
         $userName = getNameFormat($user->name, $user->username, $ueConfig['name_format']);
     }
     if ($_CB_framework->getUi() == 1) {
         if ($itsmyself) {
             $this->htmlTabTitle = sprintf(CBPTXT::Th("Your current %s"), $subTxt);
         } else {
             $this->htmlTabTitle = sprintf(CBPTXT::Th("%s's current %s"), $userName, $subTxt);
         }
     } else {
         if ($itsmyself) {
             $this->htmlTabTitle = sprintf(CBPTXT::Th("Your current and past %s"), $subTxt);
         } else {
             $this->htmlTabTitle = sprintf(CBPTXT::Th("%s's current and past %s"), $userName, $subTxt);
         }
     }
     return $this->display();
 }
	/**
	 * Fetch latest version and licensing information from versions server
	 *
	 * @param  boolean     $detailed  Gives detailed latest version description ?
	 * @return array|NULL             errorText  NULL if the key record could be fetched and stored, otherwise major error string
	 */
	public function fetchVersion( $detailed = false ) {
		global $_CB_framework;

		$return							=	null;
		if ( ! isset( $this->responses[$detailed] ) ) {
			$cbsubsVersion				=	explode( ' ', cbpaidApp::version() );
			$this->version				=	$cbsubsVersion[0];
			$this->versionminor			=	( isset( $cbsubsVersion[1] ) ? $cbsubsVersion[1] : '' );

			$formvars		=	array(	'task'					=>	'version',
										'type'					=>	'3',
										'version'				=>	'300',
										'product'				=>	$this->product,
										'productversion'		=>	$this->version,
										'productversionminor'	=>	$this->versionminor,
										'lang'					=>	$_CB_framework->getCfg( 'lang_tag' ),
										'info'					=>	( $detailed ? 'latestversiondetailed' : 'latestversionsummary' )
			);
			$random						=	sprintf( '%08x', mt_rand() );
			$formvars['sign']			=	$random . '-' . md5( $random . implode( '&', $formvars ) );

			$result						=	null;
			$status						=	null;
			$timeout					=	90;
			$live_site					=	$_CB_framework->getCfg( 'live_site' );
			$error						=	cbpaidWebservices::httpsRequest( $this->url, $formvars, $timeout, $result, $status, 'post', 'normal', '*/*', $this->https, $this->port, '', '', false, $live_site );

			$this->responses[$detailed]	=	array();
			if ($error || ( $status != 200) ) {
				$return					=	CBPTXT::T("Connection to update server failed") . ': ' . CBPTXT::T("Error") . ': ' . $error . ($status == -100 ? CBPTXT::T("Timeout") : $status);
			} else {
				$resultArray			=	explode( '-', $result );
				if ( count( $resultArray ) == 3 ) {
					$md5hash			=	md5( $resultArray[1] . $resultArray[0] );
					if ( $md5hash == $resultArray[2] ) {
						$result			=	base64_decode( $resultArray[0] );
						$arr			=	explode( '&', $result );
						$this->responses[$detailed]						=	array();
						foreach ( $arr as $v ) {
							$parts										=	explode( '=', $v );
							if ( count( $parts ) == 2 ) {
								$this->responses[$detailed][$parts[0]]	=	rawurldecode( $parts[1] );
							}
						}
						$return			=	null;
					} else {
						$return			=	CBPTXT::T("Hash mismatch");
					}
				} else {
					// echo $result;
					$return				=	CBPTXT::T("Malformed version server response");	// . $result;
				}
			}
		}
		if ( $return === null ) {
			return $this->responses[$detailed];
		}
		return $return;
	}
	/**
	 * Gives the URL of a link with plugin parameters, as HTTPS if global CBSubs setting is to use HTTPS for Forms (PCI-DSS compliance).
	 *
	 * @param  array    $paramArray        array of string with key name of parameters
	 * @param  string   $task              cb task to link to (default: userProfile)
	 * @param  boolean  $sefed             TRUE to call cbSef (default), FALSE to leave URL unsefed
	 * @param  array    $excludeParamList  of string with keys of parameters to not include
	 * @param  string   $format            'html', 'component', 'raw', 'rawrel'		(added in CB 1.2.3)
	 * @return string value of the parameter
	 */
	public function getHttpsAbsURLwithParam( $paramArray, $task = 'userProfile', $sefed = true, $excludeParamList = null, $format = 'html' ) {
		$url	=	$this->_getAbsURLwithParam( $paramArray, $task, $sefed, $excludeParamList, $format );
		if ( cbpaidApp::settingsParams()->get( 'https_posts', 0 ) ) {
			return preg_replace( '/^https?:/', 'https:', $url );
		} else {
			return $url;
		}
	}
 /**
  * Returns substitution strings
  *
  * @see cbpaidSomething::substitutionStrings()
  *
  * @param  boolean  $html                              HTML or TEXT return
  * @param  boolean  $runContentPluginsIfAllowedByPlan  DEFAULT: TRUE
  * @return array
  */
 public function substitutionStrings($html, $runContentPluginsIfAllowedByPlan = true)
 {
     $strings = parent::substitutionStrings($html, $runContentPluginsIfAllowedByPlan);
     $plan = $this->getPlan();
     // For donations, [PLAN_PRICE] is the amount just donated, as it's user-selectable:
     $strings['PLAN_PRICE'] = cbpaidMoney::getInstance()->renderPrice($this->amount, $this->currency, $html, false);
     $strings['PLAN_RATE'] = sprintf('%.2f', cbpaidApp::getCurrenciesConverter()->convertCurrency($this->currency, $plan->currency(), $this->amount));
     $strings['PLAN_FIRST_RATE'] = $strings['PLAN_RATE'];
     return $strings;
 }
 /**
  * Draws the subscription for registrations and profile views
  *
  * @param  string   $plansTitle              Title field of the plans (for validation texts)
  * @param  string   $selectionId             html input tag attribute id=''    field for the input
  * @param  string   $selectionName           html input tag attribute name=''  field for the input
  * @param  string   $selectionValue          html input tag attribute value='' field for the input
  * @param  string   $insertBeforePrice       HTML text to insert after description of this item but before price
  * @param  string   $insertAfterDescription  HTML text to insert after this item as sub-items
  * @param  boolean  $selected                TRUE if the item is selected
  * @param  string   $reason                  Payment reason: 'N'=new subscription (default), 'R'=renewal, 'U'=update
  * @param  boolean  $displayDescription      TRUE: display description also
  * @param  boolean  $displayPrice            TRUE: display price/price selection also
  * @param  int      $user_id                 User-id for whom the plan is drawn
  * @return string                            HTML
  */
 public function drawProduct($plansTitle, $selectionId, $selectionName, $selectionValue, $insertBeforePrice, $insertAfterDescription, $selected, $reason, $displayDescription, $displayPrice, $user_id)
 {
     parent::drawProduct($plansTitle, $selectionId, $selectionName, $selectionValue, $insertBeforePrice, $insertAfterDescription, $selected, $reason, $displayDescription, $displayPrice, $user_id);
     $this->periodPrice = null;
     if ($displayPrice) {
         $this->_setOptionNames($selectionId, $selectionName, true);
         $this->currency = $this->_model->get('currency');
         if (!$this->currency) {
             $this->currency = cbpaidApp::settingsParams()->get('currency_code');
         }
         $cbpaidMoney = cbpaidMoney::getInstance();
         $currencySymbol = $cbpaidMoney->renderCurrencySymbol($this->currency, true);
         if ($cbpaidMoney->currencyAfterOrNotBefore()) {
             $currencySymbolAfter = ' ' . $currencySymbol;
             $currencySymbolBefore = '';
         } else {
             $currencySymbolAfter = '';
             $currencySymbolBefore = $currencySymbol . ' ';
         }
         $this->fixedchoices = $this->_model->getParam('fixedchoices', 1);
         $this->defaultchoice = $this->_model->getParam('defaultchoice', '');
         $this->donateamounts = explode(',', $this->_model->getParam('donateamount', ''));
         $this->_trimArray($this->donateamounts);
         if ($this->fixedchoices == 2 && count($this->donateamounts) == 1) {
             $this->periodPrice = '<input type="hidden" name="' . $this->_donselName . '" value="' . $this->donateamounts[0] . '" />' . '<span class="cbregDonationRate">' . $this->_model->displayPeriodPrice($reason, 'I', 0, null, null, true) . '</span>';
         } elseif ($this->fixedchoices > 1) {
             $options = array();
             $options[] = moscomprofilerHTML::makeOption('', htmlspecialchars(CBPTXT::T("--- Select amount ---")));
             $this->_valuesToOptions($options, $this->donateamounts, $this->currency);
             if ($this->fixedchoices == 3) {
                 $options[] = moscomprofilerHTML::makeOption('0', htmlspecialchars(CBPTXT::T("Other...")));
             }
             $this->periodPrice = moscomprofilerHTML::selectList($options, $this->_donselName, 'class="inputbox cbregDonationSelector"', 'value', 'text', $this->defaultchoice, 2, false);
         }
         if ($this->fixedchoices == 3) {
             $this->periodPrice = '<span class="cbregDonationSelect">' . $this->periodPrice . '</span>';
         }
         $hiddenStyle = '';
         if ($this->fixedchoices != 2) {
             if ($this->fixedchoices == 3 && (in_array($this->defaultchoice, $this->donateamounts) || $this->defaultchoice == '')) {
                 $hiddenStyle = ' style="display:none;"';
                 $defaultDonateValue = '';
             } else {
                 $defaultDonateValue = $this->defaultchoice;
             }
             /*	if ( ( $this->fixedchoices == 1 ) {
             					$defaultDonateValue	=	$this->defaultchoice;
             				}
             			*/
             $this->periodPrice .= '<span class="cbregDonationValue" id="' . $selectionId . 'donspan' . '"' . $hiddenStyle . '>' . $currencySymbolBefore . '<input type="text" size="12" name="' . $this->_donvalName . '" id="' . $selectionId . 'donval' . '" class="inputbox cbregDonationFreeValue" value="' . htmlspecialchars($defaultDonateValue) . '"' . ' />' . $currencySymbolAfter . '</span>';
         }
     }
     return $this->display();
 }
 /**
  * Draws the subscription for registrations and profile views
  *
  * @param  int        $invoicesNumber  array of cbpaidPaymentBasket  of Completed and Pending baskets
  * @param  UserTable  $user            reflecting the user being displayed (here null)
  * @param  boolean    $itsmyself       user is logged in user
  * @param  string     $periodText      if non-empty, text of the period showing invoices
  * @return string
  */
 public function drawInvoicesList($invoicesNumber, $user, $itsmyself, $periodText)
 {
     $this->user = $user;
     $this->plansTitle = $this->_invoicesTitle($invoicesNumber, $user, $itsmyself, $periodText);
     $params = cbpaidApp::settingsParams();
     $this->show_invoice_numbers = $params->get('invoice_number_format') && $params->get('show_invoices');
     $baseClass = cbpaidApp::getBaseClass();
     foreach ($this->_model as $i) {
         $this->invoicesUrls[$i->id] = $baseClass->getInvoiceUrl($i);
     }
     return $this->display('default');
 }
 /**
  * Returns either a hidden form with a visible button or redirects directly to payment processing page
  * THIS CancelPay gateway's getPaymentBasketProcess is a bit DIFFERENT, as it just returns a string with the link to cancel.
  *
  * @param  UserTable            $user           object reflecting the user being registered (it can have id 0 or be NULL in future)
  * @param  cbpaidPaymentBasket  $paymentBasket  Order Basket to be paid
  * @param  string               $redirectNow    'redirect', 'radios', 'buttons', other: return null (see above)
  * @return string|array                         array: See above, OR string: HTML to display in buttons area
  */
 public function getPaymentBasketProcess($user, $paymentBasket, $redirectNow)
 {
     $ret = null;
     if ($redirectNow == 'redirect') {
         return array($this->getCancelUrl($paymentBasket));
     } else {
         $params = cbpaidApp::settingsParams();
         $return_cancel_url = $this->getCancelUrl($paymentBasket);
         $ret .= '<div><a href="' . $return_cancel_url . '">' . CBPTXT::Th($params->get('cancel_subscription_link_text', 'Cancel payment and subscription')) . '</a></div>';
         $ret = '<div class="cbpaidCCbutton" id="cbpaidButtcancel">' . $ret . '</div>';
     }
     return $ret;
 }
 /**
  * Draws the plans upgrade proposals
  * 
  * @param  UserTable  $user
  * @param  int        $plansDisplayed
  * @param  string     $htmlUpgrades
  * @param  string     $htmlspecialcharedBaseUrl
  * @param  array      $hiddenFlds
  * @param  array      $buttonTexts
  * @param  string     $buttonName
  * @return string
  */
 public function drawUserUpgradePlans($user, $plansDisplayed, $htmlUpgrades, $htmlspecialcharedBaseUrl, $hiddenFlds, $buttonTexts, $buttonName)
 {
     $this->htmlUpgrades = $htmlUpgrades;
     $this->htmlspecialcharedBaseUrl = $htmlspecialcharedBaseUrl;
     $this->hiddenFlds = $hiddenFlds;
     $this->buttonName = $buttonName;
     $this->buttonText = implode(' / ', $buttonTexts);
     $subTxt = CBPTXT::T(cbpaidApp::settingsParams()->get('subscription_name', 'subscription'));
     if ($plansDisplayed == 1) {
         $this->htmlTitle = sprintf(CBPTXT::Th("Your current %s upgrade possibility:"), $subTxt);
     } else {
         $this->htmlTitle = sprintf(CBPTXT::Th("Your current %s upgrade possibilities:"), $subTxt);
     }
     return $this->display();
 }
 /**
  * Draws the user profile tab "Subscriptions" (if enabled, user is the profile owner, and something to display.
  * 
  * @param  string      $plansTitle
  * @param  string      $htmlPlans
  * @return array|null
  */
 public function drawRegistrationPlans($plansTitle, $htmlPlans)
 {
     $this->plansTitle = $plansTitle;
     $this->htmlPlans = $htmlPlans;
     $htmlValue = $this->display();
     $description = null;
     $uniqueId = 'cbregplans';
     $displayOnTwoLines = cbpaidApp::settingsParams()->get('regDisplayLines', 2) == 2;
     $tab = $this->_model;
     if ($htmlValue) {
         return array(cbTabs::_createPseudoField($tab, $this->plansTitle, $htmlValue, $description, $uniqueId, $displayOnTwoLines));
     } else {
         return null;
     }
 }
	/**
	 * Loads a subscription of a plan and returns an object of the corresponding class
	 *
	 * @param  int  $planId          Id of plan
	 * @param  int  $subscriptionId  Id of subscription within the plan $planId
	 * @return cbpaidSomething       The Something of plan $planId and subscription-id $subscriptionId
	 */
	public function & loadSomething( $planId, $subscriptionId ) {
		static $_planSubscriptions		=	array();
		$planId							=	(int) $planId;
		$subscriptionId					=	(int) $subscriptionId;

		if ( ! isset( $_planSubscriptions[$planId][$subscriptionId] ) ) {
			$plansMgr														=&	cbpaidPlansMgr::getInstance();	// can't access $this here as in static call.
			if ( $planId ) {
				$plan														=&	$plansMgr->loadPlan( $planId );
				if ( $plan ) {
					if ( $subscriptionId ) {

						$_planSubscriptions[$planId][$subscriptionId]		=	$plan->newSubscription();
						/** @noinspection PhpUndefinedMethodInspection (Due to limitation of IDE) */
						if ( $_planSubscriptions[$planId][$subscriptionId]->load( $subscriptionId ) ) {
							if ( $_planSubscriptions[$planId][$subscriptionId]->plan_id == $planId ) {

								return $_planSubscriptions[$planId][$subscriptionId];

							}
							cbpaidApp::setLogErrorMSG( 5, $plan, sprintf( 'loadSomething::planid %d of subid %d does not match planid %d.', $_planSubscriptions[$planId][$subscriptionId]->plan_id, $subscriptionId, $planId ), null );
						} else {
							cbpaidApp::setLogErrorMSG( 5, $plan, sprintf( 'loadSomething::subid %d with planid %d could not load.', $subscriptionId, $planId ), null );
						}
						unset( $_planSubscriptions[$planId][$subscriptionId] );

					} else {
						cbpaidApp::setLogErrorMSG( 5, $plan, sprintf( 'loadSomething::plan id: %d but no subscription id.', $planId ), null );
					}
				} else {
					cbpaidApp::setLogErrorMSG( 5, $plan, sprintf( 'loadSomething::plan id: %d is missing in database for subscription id: %d', $planId, $subscriptionId ), null );
				}

				$null													=	null;
				return $null;

			} else {
				trigger_error( 'loadSomething::no plan id.', E_USER_ERROR );
				exit;
			}
		}
		return $_planSubscriptions[$planId][$subscriptionId];
	}
 /**
  * USED by XML interface ONLY !!! Renders main currency conversion rates
  *
  * @param  string           $value
  * @param  ParamsInterface  $params
  * @return string                    HTML to display
  */
 public function renderMainRate($value, $params)
 {
     $textCurrency = $params->get('currency_code', 'USD');
     $textSecondaryCurrency = $params->get('secondary_currency_code');
     $price = 1.0;
     // $priceText					=	$this->renderPrice( $price, $textCurrency, true );
     if ($textSecondaryCurrency && $textSecondaryCurrency != $textCurrency) {
         $_CBPAY_CURRENCIES = cbpaidApp::getCurrenciesConverter();
         $secondaryPrice = $_CBPAY_CURRENCIES->convertCurrency($textCurrency, $textSecondaryCurrency, $price);
         if ($secondaryPrice !== null) {
             // we do not want roundings here:
             // $secondaryPriceText	=	$this->renderPrice( $secondaryPrice, $textSecondaryCurrency, true );
             // return $secondaryPriceText . ' / ' . $priceText;
             return sprintf('%s %0.2f / %s %0.2f', $textSecondaryCurrency, $secondaryPrice, $textCurrency, $price);
         } else {
             $error = $_CBPAY_CURRENCIES->getError();
             return '<span style="color:red">' . $error . '</span>';
         }
     }
     return null;
 }
Example #13
0
	/**
	 * returns price (rate) in the given currency.
	 *
	 * @param  float       $amount            Amount to convert
	 * @param  string      $fromCurrencyCode  ISO currency
	 * @param  string      $toCurrencyCode    ISO currency
	 * @param  boolean     $withRounding      If roundings corresponding to params should be done
	 * @param  boolean     $withMarkup        If markup corresponding to params should be done
	 * @return float|null                      returns $price in $currency_code or null if it can not convert.
	 */
	public function convertPrice( $amount, $fromCurrencyCode, $toCurrencyCode, $withRounding, $withMarkup ) {
		if ( $toCurrencyCode && ( $toCurrencyCode != $fromCurrencyCode ) ) {
			$_CBPAY_CURRENCIES		=&	cbpaidApp::getCurrenciesConverter();
			$amount					=	$_CBPAY_CURRENCIES->convertCurrency( $fromCurrencyCode, $toCurrencyCode, $amount );		// null if cannot convert

			if ( $amount !== null ) {
				if ( $withMarkup ) {
					$markup			=	$this->params->get( 'currency_conversion_markup_percent', 0 );
					if ( $markup ) {
						$amount		=	$amount * ( 1.0 + ( $markup / 100.0 ) );
					}
				}

				if ( $withRounding ) {
					$roundings		=	$this->params->get( 'rounding_converted_currency_price', 0 );
					$priceRoundings	=	( $roundings ? $this->params->get('price_roundings', 100 ) : 100 );
					$amount			=	round( $amount * $priceRoundings ) / $priceRoundings;
				}
			}
		}
		return $amount;
	}
	/**
	 * When triggered, before starting to make changes this method should be called
	 * Transition: -> E{$substate}
	 * 
	 * @param  string  $substate
	 * @return boolean                TRUE: got lock to perform scheduled task, FALSE: no scheduling needed here (and no transition made)
	 */
	public function attemptScheduledTask( $substate = '' ) {
		if ( substr( $this->_baseObject->scheduler_state, 0, 1 ) == 'E' ) {
			// It was Executing: check for iterations before resetting to 'S' (with error log).

			if ( strlen( $this->_baseObject->scheduler_state ) == 1 ) {
				// Backwards compatibility:
				$this->_baseObject->scheduler_state			.=	'1';
			}

			$iteration										=	(int) $this->_baseObject->scheduler_state[1];
			if ( ++$iteration <= $this->maxExecWaitIterations ) {
				$this->_baseObject->scheduler_state[1]		=	(string) $iteration;
				$this->_baseObject->store();
			} else {
				$this->_baseObject->scheduler_state			=	'S';
				cbpaidApp::setLogErrorMSG( 4, $this->_baseObject, CBPTXT::P("Scheduler for this basket has stayed in execution state for [NUMBER_OF_CRONS] cron cycles. Resetting execution state.", array( '[NUMBER_OF_CRONS]' => $this->maxExecWaitIterations ) ), null );
			}
		}

		// Now normal case:
		if ( $this->_baseObject->scheduler_state == 'S' ) {
			// it was scheduled:
			$this->_baseObject->scheduler_state				=	'E1' . $substate;	// Executing
			return $this->_baseObject->store();
		}
		return false;
	}
 /**
  * Displays $text inside a standard CB div, and sets page title and pathway too
  *
  * @param  string  $text
  * @return string
  */
 public static function displayWithTemplate($text)
 {
     global $_CB_framework;
     $regTitle = strip_tags(CBPTXT::T(cbpaidApp::settingsParams()->get('regTitle', "Subscriptions")));
     outputCbTemplate();
     $_CB_framework->setPageTitle($regTitle);
     $_CB_framework->appendPathWay($regTitle);
     $pre = '<div class="cbPageOuter"><div class="cbPageInner" id="cbregField">';
     $post = '</div></div><div class="cbClr"> </div>';
     return $pre . $text . $post;
 }
 /**
  * Sets the text of the last error and logs it to the history logger
  *
  * @param  int               $log_priority      Priority of message (UNIX-type): 0: Emergency, 1: Alert, 2: Critical, 3: Error, 4: Warning, 5: Notice, 6: Info, 7: Debug
  * @param  cbpaidTable|null  $object            Object stored in database, so that table name of table and id of key can be stored with the error
  * @param  string            $logMessagePrefix  Error message prefix for the logged message (simple non-html text only): will be prepended with ': '
  * @param  string            $userMessage       Error message for user (simple non-html text only)
  */
 public static function setLogErrorMSG($log_priority, $object, $logMessagePrefix, $userMessage)
 {
     global $_CB_database;
     $logObject = new cbpaidHistory($_CB_database);
     $logText = $logMessagePrefix ? $logMessagePrefix . ($userMessage ? ': ' . $userMessage : '') : $userMessage;
     $logObject->logError($log_priority, $logText, $object);
     if ($userMessage) {
         cbpaidApp::getBaseClass()->_setErrorMSG($userMessage);
     }
 }
 /**
  * Saves record payment view
  *
  * @param  int          $paymentBasketId
  * @return null|string
  */
 public static function saveRecordPayment($paymentBasketId)
 {
     cbpaidApp::loadLang('admin');
     $paymentRecorder = new self();
     $exists = $paymentBasketId && $paymentRecorder->load((int) $paymentBasketId);
     if ($exists) {
         if ($paymentRecorder->authoriseAction('cbsubs.recordpayments')) {
             $return = $paymentRecorder->saveRecordPaymentForm();
         } else {
             $return = CBPTXT::T("You are not authorized to record payments.");
         }
     } else {
         $return = CBPTXT::T("No unpaid payment basket found.");
     }
     return $return;
 }
 /**
  * View for <param  type="private" class="cbpaidParamsExt" method="checkPluginsPublished">...
  *
  * @param  string              $value                  Stored Data of Model Value associated with the element
  * @param  ParamsInterface     $pluginParams           Main settigns parameters of the plugin
  * @param  string              $name                   Name attribute
  * @param  CBSimpleXMLElement  $param                  This XML node
  * @param  string              $control_name           Name of the control
  * @param  string              $control_name_name      css id-encode of the names of the controls surrounding this node
  * @param  boolean             $view                   TRUE: view, FALSE: edit
  * @param  cbpaidTable         $modelOfData            Data of the Model corresponding to this View
  * @param  cbpaidTable[]       $modelOfDataRows        Displayed Rows if it is a table
  * @param  int                 $modelOfDataRowsNumber  Total Number of rows
  * @return null|string
  */
 public function checkPluginsPublished($value, &$pluginParams, $name, &$param, $control_name, $control_name_name, $view, &$modelOfData, &$modelOfDataRows, &$modelOfDataRowsNumber)
 {
     global $_PLUGINS;
     $groups = explode(',', $param->attributes('groups'));
     $action = $param->attributes('action');
     $path = $param->attributes('path');
     $version = cbpaidApp::version();
     $html = null;
     foreach ($groups as $group) {
         $matches = null;
         if (preg_match('/^([^\\[]+)\\[(.+)\\]$/', $group, $matches)) {
             $classId = $matches[2];
             $group = $matches[1];
         } else {
             $classId = null;
         }
         $_PLUGINS->loadPluginGroup($group, $classId, 0);
         $loadedPlugins = $_PLUGINS->getLoadedPluginGroup($group);
         foreach ($loadedPlugins as $plugin) {
             if (!$classId || substr($classId, -1) == '.' && substr($plugin->element, 0, strlen($classId)) == $classId || $plugin->element == $classId) {
                 $element = $_PLUGINS->loadPluginXML('action', $action, $plugin->id);
                 $viewModel = $element->getElementByPath($path);
                 if (!$path || $viewModel) {
                     if ($plugin->published == 0) {
                         $html .= '<div class="cbWarning">' . sprintf(CBPTXT::Th("The integration plugin '%s' is installed but not published."), htmlspecialchars($plugin->name)) . '</div>';
                     }
                     $cbsubsv = $element->getElementByPath('cbsubsversion');
                     if ($cbsubsv) {
                         if (!cbStartOfStringMatch($version, $cbsubsv->attributes('version'))) {
                             $html .= '<div class="cbWarning">' . sprintf(CBPTXT::T("The CBSubs integration plugin '%s' is for another CBSubs version %s."), htmlspecialchars($plugin->name), htmlspecialchars($cbsubsv->attributes('version'))) . '</div>';
                         }
                     } else {
                         $html .= '<div class="cbWarning">' . sprintf(CBPTXT::T("The CBSubs integration plugin '%s' has no CBSubs version information in XML."), htmlspecialchars($plugin->name)) . '</div>';
                     }
                 }
             }
         }
     }
     /*
     		if ( $html ) {
     			$html			=	'<div class="cbDisabled">'
     							.	CBPTXT::Th("Following CBSubs integration CB plugins are installed but not published (so not active in front-end)")
     							.	':'
     							.	'</div>'
     							.	$html
     							;
     		}
     */
     return $html;
 }
Example #19
0
	/**
	 * Renders a price in default currency, formatting roundings corresponding to $params
	 *
	 * @param  float         $price      Price: positive float or NULL
	 * @param  boolean       $html       HTML mode or text mode
	 * @param  boolean       $roundings  TRUE: do round, FALSE: do not round display
	 * @param  boolean       $displaySecondaryCurrency   TRUE: display secondary currencies, FALSE: only display in $this->currency()
	 * @return string                    HTML or Text
	 */
	public function renderPricesWithConversion( $price, $html, $roundings = true, $displaySecondaryCurrency = true ) {
		$textCurrency				=	$this->currency();

		$params						=&	cbpaidApp::settingsParams();
		$textSecondaryCurrency		=	$params->get( 'secondary_currency_code' );

		if ( $displaySecondaryCurrency && ( $price != 0 ) && $textSecondaryCurrency && ( $textSecondaryCurrency != $textCurrency ) ) {
			// Initialize convertion+rendering function:
			$this->_renderPriceInCurrency( $price, $html, $roundings );

			// Get and fix format:
			$format					=	$params->get( 'secondary_price_display_format', '[MAIN_CURRENCY_PRICE] (~ [SECONDARY_CURRENCY_PRICE])' );
			if ( $html ) {
				if ( strpos( $format, '<' ) === false ) {
					$format			=	str_replace( array( ' ', '~' ), array( '&nbsp;', '&asymp;' ), $format );
				}
			} else {
				$format				=	str_replace( array( '&nbsp;', '&asymp;' ), array( ' ', '~' ), strip_tags( $format ) );
			}

			// Set main and secondary currencies:
			$format					=	str_replace( array( '[MAIN_CURRENCY_PRICE]', '[SECONDARY_CURRENCY_PRICE]' ), array( '[' . $textCurrency . ']', '[' . $textSecondaryCurrency . ']' ), $format );
			// Render prices:
			$priceText				=	preg_replace_callback( '/\[(...)\]/', array( $this, '_renderPriceInCurrency' ), $format );
		} else {
			// Single currency simple case:
			$priceText				=	$this->renderPrice( $price, $textCurrency, $html, $roundings );
		}

		return $priceText;
	}
	/**
	 * Returns a cbpaidGatewaySelectorButton object parameters for rendering an HTML form with a visible button and hidden fields for the gateway
	 * Or a string with HTML content instead (not recommended)
	 * 
	 * @param  cbpaidPaymentBasket  $paymentBasket  paymentBasket object
	 * @param  string               $subMethod      'single', 'subscribe' or gateway-specific string (e.g. credit-card brand)
	 * @param  string               $paymentType    'single' or 'subscribe' or for subscriptions 'cancel'
	 * @return cbpaidGatewaySelectorButton                  or string with HTML
	 */
	protected function getPayButtonRecepie( $paymentBasket, $subMethod, $paymentType )
	{
		// Settings for Free Trial and Order Now buttons are stored in global CBSubs settings:
		$params					=	cbpaidApp::settingsParams();

		// Generate URLs for payment:
		$pspUrl					=	$this->pspUrl( $paymentBasket, ( $paymentType == 'subscribe' ) );
		$requestParams			=	$this->getSinglePaymentRequstParams( $paymentBasket );
		$customImage			=	$params->get( $this->_button . '_custom_image' );
		$titleText				=	( $this->_button == 'freetrial' ? CBPTXT::T("Subscribe to free trial period only") : CBPTXT::T("Confirm Order") );
		$altText				=	( $this->_button == 'freetrial' ? CBPTXT::T("Free Trial") :  CBPTXT::T("Confirm Order") );
		$butId					=	'cbpaidButt' . strtolower( $this->_button );

		if ( $customImage == '' ) {
			$customImage		=	$params->get( $this->_button . '_image', 'components/com_comprofiler/plugin/user/plug_cbpaidsubscriptions/icons/cards/'
								.	( $this->_button == 'freetrial' ? 'cc_big_orange_free_trial.gif' : 'cc_big_orange_confirm_order.gif' ) );
		}
		$payNameForCssClass		=	$this->_button;
		
		return cbpaidGatewaySelectorButton::getPaymentButton( $this->getAccountParam( 'id' ), $subMethod, $paymentType, $pspUrl, $requestParams, $customImage, $altText, $titleText, $payNameForCssClass, $butId );
	}
	/**
	* gets the chosen plans from the form, and checks if they are allowed for that user
	* also gets the options of the plans
	* In detail:
	* gets an array of array of int as an array of int (removing first level), verifying that if index is not 0 the parent exists
	* In each plan object there is a ->_options variable with a Registry object with the option values of the plan
	*
	* @param  UserTable        $user            Reflecting the user being registered or saved
	* @param  string           $name            name of parameter in REQUEST URL
	* @param  cbpaidProduct[]  $allowedPlans    array of cbpaidProduct  which are allowed
	* @param  boolean          $isRegistration  TRUE: Registration process (guest), or FALSE: upgrade-process (logged-in user)
	* @param  string           $reason          Subscription reason: 'N'=new subscription (default), 'R'=renewal, 'U'=update
	* @param  boolean          $returnPlans     TRUE: returns plan objects or FALSE: returns plan ids only.
	* @param  string           $postfix         postfix for identifying multiple plans spaces (optional)
	* @return int[]|cbpaidProduct[]|string     ARRAY of int|of cbpaidProducts : Plans which are selected within hierarchy (according to the post, to be rechecked !) or STRING: error message.
	*/
	protected function & _planGetAndCheckReqParamArray( &$user, $name, &$allowedPlans, $isRegistration, $reason, $returnPlans = false, $postfix = '' ) {
		global $_CB_framework, $_POST;

		$params							=&	cbpaidApp::settingsParams();
		$enableFreeRegisteredUser		=	$params->get( 'enableFreeRegisteredUser', 1 );
		$createAlsoFreeSubscriptions	=	$params->get( 'createAlsoFreeSubscriptions', 0 );

		$ui								=	$_CB_framework->getUi();
		if ( ! $isRegistration ) {
			if ( $ui == 1 ) {
				$userId					=	(int) cbGetParam( $_POST, 'user', 0 );
			} else {
				$userId					=	(int) cbGetParam( $_POST, 'id', 0 );
			}
		} else {
			$userId						=	null;
		}

		$selectedPlanIds							=	$this->_plangetReqParamArray( $name, $postfix );
		/// $validSub									=	array();
		// 1. checks that selected plans hierarchy is respected:
		$ok											=	true;
		$plansMgr									=	null;
		foreach ( $selectedPlanIds as $id ) {
			if ( $id != 0 ) {						// ignore "None" plan in backend edit profile
				$ok									=	false;
	
				// foreach ( $allowedPlans as $planid => $p ) {
				if ( isset( $allowedPlans[(int) $id] ) ) {
					$p								=	$allowedPlans[(int) $id];
	
					if ( $id == $p->id ) {
						$parentOk					=	true;
						$parentId					=	$p->get( 'parent' );
						if ( $parentId != 0 ) {
							// the selected plan has a parent plan: check if parent plan is also chosen or already subscribed and active:
							$parentOk				=	false;
							foreach ($selectedPlanIds as $selPlanId ) {
								if ( $parentId == $selPlanId ) {
									$parentOk		=	true;
									break;
								}
							}
							if ( ( ! $isRegistration ) && ( ! $parentOk ) ) {
								// try to see if user is subscribed already to the parent plan:
								if ( $userId ) {
									if ( $plansMgr === null ) {
										$plansMgr	=&	cbpaidPlansMgr::getInstance();
									}
									$plan			=	$plansMgr->loadPlan( $parentId );
									/** @var $plan cbpaidProduct */
									if ( $plan ) {
										// Check if allow free lifetime users without need to create such subscriptions:
										if ( $enableFreeRegisteredUser && ( ! $createAlsoFreeSubscriptions ) && $plan->isLifetimeValidity() && $plan->isFree() ) {
											$parentOk		=	true;
										} else {
											$sub			=	$plan->newSubscription();
											/** @var $sub cbpaidSomething */
											if ( $sub->loadValidUserSubscription( $userId ) ) {
												$parentOk	=	true;
												/// $validSub[$parentId]		=	$sub->id;
											}
										}
									}
								}
							}
						}
						if ( $parentOk ) {
							$ok						=	true;
						}
						break;
					}
				}
				if ( ! $ok ) {
					break;
				}
			}
		}

		if ( ! $ok ) {
			$selectedPlanIds								=	CBPTXT::T("Chosen plans combination is not allowed (you must choose coherent plans selection, e.g. parent subscriptions to a plan must be active).");
		} else {
			// 2. Check that all exclusivities are respected:
			$plansMgr										=&	cbpaidPlansMgr::getInstance();
			// 2.a. build array of exclusive [parent][plan]:
			$exclusiveChildren								=	array();
			// 2.a.1. add the plans just selected now:
			foreach ($allowedPlans as $id => $p ) {
				if ( $p->get( 'exclusive' ) ) {
					$exclusiveChildren[$p->get( 'parent' )][$p->get( 'id' )]	=	( in_array( $id, $selectedPlanIds ) ? 1 : 0 );
				}
			}
			// 2.a.2. add the plans already subscribed with active subscription (if we are not just upgrading that level):
			$ValidUserPlans									=	array();
			$validSubExists									=	array();
			if ( ( ! $isRegistration ) && $userId ) {
				foreach ( $exclusiveChildren as $parentId => $exclPlansArray ) {
					if ( $parentId != 0 ) {
						$plan								=	$plansMgr->loadPlan( $parentId );
						if ( $plan ) {
							$sub							=	$plan->newSubscription();
							$ValidUserPlans[$parentId]		=	( $sub->loadValidUserSubscription( $userId ) );
						} else {
							$selectedPlanIds				=	CBPTXT::T("Chosen plan has a parent plan configured that doesn't exist anymore.");
						}
					}
					$numberOfSelected						=	array_sum( $exclPlansArray );
					if ( $numberOfSelected == 0 ) {
						$firstFreeLifeTime					=	array();
						// foreach ( $exclPlansArray as $childId => $selected )
						foreach ( array_keys( $exclPlansArray ) as $childId ) {
							$plan							=	$plansMgr->loadPlan( $childId );
							if ( ( ! isset( $firstFreeLifeTime[$parentId] ) ) && ( $enableFreeRegisteredUser && ( ! $createAlsoFreeSubscriptions ) && $plan->isLifetimeValidity() && $plan->isFree() ) ) {
								$firstFreeLifeTime[$parentId]	=	$plan->get( 'id' );
							}
							if ( ! isset( $ValidUserPlans[$childId] ) ) {
								$sub						=	$plan->newSubscription();
								$ValidUserPlans[$childId]	=	( $sub->loadValidUserSubscription( $userId ) );
							}
							if ( $ValidUserPlans[$childId] ) {
								$exclusiveChildren[$parentId][$childId]		=	1;
								$validSubExists[$parentId]						=	1;
							}
						}
					}
				}
			}
			// 2.b. check that exactly 1 exclusive plan is selected at each level (including still valid subscribed plans) which matters:
			if ( ! ( ( $ui == 2 ) && ( $selectedPlanIds == array( '0' ) ) ) ) {		// ignore "None" plan in backend edit profile
				foreach ( $exclusiveChildren as $parentId => $exclPlansArray ) {
					$numberOfSelected						=	array_sum( $exclPlansArray );
					if ( $numberOfSelected > 1 ) {
						$selectedPlanIds					=	CBPTXT::T("Chosen plans combination is not allowed (you can't choose more than one mandatory plan).") . $numberOfSelected;
						break;
					}
					elseif ( ( $numberOfSelected == 0 ) && ( ! isset( $validSubExists[$parentId] ) ) && ( ! isset( $firstFreeLifeTime[$parentId] ) ) ) {
						if ( ( $parentId == 0 ) || in_array( $parentId, $selectedPlanIds ) || ( isset( $ValidUserPlans[$parentId] ) && ( $ValidUserPlans[$parentId] == true ) ) )
						{
							$selectedPlanIds				=	CBPTXT::T("Chosen plans combination is not allowed (you must choose coherent plans selection, e.g. mandatory subscription(s) must be active or mandatory plan(s) must be chosen).");
							$names							=	array();
							foreach ( array_keys( $exclPlansArray ) as $childId ) {
								$exclPlan					=&	$plansMgr->loadPlan( $childId );
								/** @var $exclPlan cbpaidProduct */
								$names[]					=	$exclPlan->get( 'name' );
							}
							if ( $parentId ) {
								$parentPlan					=&	$plansMgr->loadPlan( $parentId );
								/** @var $parentPlan cbpaidProduct */
								$parentName					=	$parentPlan->get( 'name' );
								$selectedPlanIds			.=	' ' . CBPTXT::T( sprintf( "'%s' has mandatory options '%s' and none is selected." , $parentName, implode( "', '", $names ) ) );
							}
							break;
						}
					}
				}
			}
			// 3. Checks that all selected plans' conditions are met:
			if ( is_array( $selectedPlanIds ) ) {
				foreach ( $selectedPlanIds as $id ) {
					if ( $id ) {
						$plan								=&	$plansMgr->loadPlan( $id );
						if ( $plan ) {
							if ( ! $plan->checkActivateConditions( $user, $reason, $selectedPlanIds ) ) {
								// Error text will be in selectedPlanIds in case of error returning false:
								break;
							}
						}
					}
				}
			}
			// 4. Checks done:
			if ( $returnPlans && is_array( $selectedPlanIds ) && ( count( $selectedPlanIds ) > 0 ) ) {
				// if returning selected plans, sort them in same order and with same keys as corresponding allowed plans:
				global $_PLUGINS;
				$_PLUGINS->loadPluginGroup( 'user', 'cbsubs.' );
				$_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin');

				$selectedPlans								=	array();
				foreach ($allowedPlans as $id => $p ) {
					if ( in_array( $id, $selectedPlanIds ) ) {
						/** @var cbpaidProduct[] $selectedPlans */
						$selectedPlans[(int) $id]			=	$allowedPlans[$id];
						$selectionId						=	'plan' . $id;
						$selectionName						=	'plan' . ( $selectedPlans[$id]->get( 'exclusive' ) ? 'E' : 'N' ) . '[' . (int) $selectedPlans[$id]->parent . ']';
						$selectionValue						=	$id;
						$view								=	$selectedPlans[$id]->getViewer();

						$paramsOrString						=	$view->getOptions( $selectionId, $selectionName, $selectionValue, $reason );
						if ( is_string( $paramsOrString ) ) {
							$selectedPlans					=	$paramsOrString;		// error message
							break;
						}
						$selectedPlans[(int) $id]->_options		=	$paramsOrString;
						$selectedPlans[(int) $id]->_integrations	=	new Registry( '' );
						$_PLUGINS->trigger( 'onCPayAfterPlanSelected', array( &$selectedPlans[(int) $id], &$selectedPlans[(int) $id]->_integrations , $reason ) );
						if ( $_PLUGINS->is_errors() ) {
							$selectedPlans							=	$_PLUGINS->getErrorMSG();
							break;
						}
					}
				}
				return $selectedPlans;
			}
		}
		return $selectedPlanIds;
	}
	/**
	 * Returns remaining value of a subscription with this plan in the plan's currency
	 * at $time when it's expiring at $expiryDate
	 *
	 * @param  int                 $time          Unix-time
	 * @param  string              $expiryDate    SQL datetime
	 * @param  int                 $occurrence    = 0 : first occurrence, >= 1: next occurrences
	 * @param  boolean             $upgraded_sub  TRUE if the underlying subscription is an upgrade from another subscription
	 * @param  cbpaidUsersubscriptionRecord  $subscription  the subscription
	 * @return float                              value
	 */
	public function remainingPriceValue( $time, $expiryDate, $occurrence, $upgraded_sub, &$subscription ) {
		if ( $occurrence == 0 ) {
			if ( $upgraded_sub ) {
				$reason			=	'U';
			} else {
				$reason			=	'N';
			}
		} else {
			$reason				=	'R';
		}

		$quantity				=	1;			//TBD LATER

		$varName				=	$this->getPlanVarName( $reason, $occurrence, 'validity' );
		// $varRate				=	$this->getPlanVarName( $reason, $occurrence, 'rate' );
		$fullPrice				=	$this->getPrice( $this->currency(), $subscription, $reason, $occurrence, $time, 0, $quantity );
		if ( ( $this->get( 'prorate' ) == 0 ) || ( $fullPrice == 0 ) || ( $fullPrice === false ) || ( ! $this->checkValid( $expiryDate, $time ) ) ) {
			// No-prorate plans, as well as free or expired subscriptions don't have a remaining value:
			$roundedRemaingValue				=	0;
		} elseif ( $expiryDate == null ) {
			$roundedRemaingValue				=	$fullPrice;
		} else {
			list($y,  $c,  $d,  $h,  $m,  $s )	=	sscanf( $expiryDate, '%d-%d-%d %d:%d:%d' );
			$remainingPeriod					=	mktime($h, $m, $s, $c, $d, $y) - $time;
			$fullPeriod							=	$this->getFullPeriodValidityTime( $time, $varName );
			if ( ( $fullPeriod === null ) || ( $fullPeriod == 0 ) ) {
				// lifetime or just expired:
				$roundedRemaingValue			=	0;
			} else {
				$remaingValue					=	( $remainingPeriod / $fullPeriod ) * $fullPrice;
				$params							=&	cbpaidApp::settingsParams();
				$priceRoundings					=	$params->get( 'price_roundings', 100 );
				$roundedRemaingValue			=	floor( $remaingValue * $priceRoundings ) / $priceRoundings;
				if ( $roundedRemaingValue > $fullPrice ) {	// got a bonus ?
					$roundedRemaingValue		=	$fullPrice;
				}
			}
		}
		return $roundedRemaingValue;
	}
 /**
  * Renders the rate of $this payment item
  *
  * @param  string       $variable
  * @param  boolean      $output   'html', ...
  * @param  boolean      $rounded
  * @return string|null
  */
 private function renderTotalRate($variable, $output, $rounded = false)
 {
     $renderedBasketPrice = null;
     $params = cbpaidApp::settingsParams();
     if ($params->get('totalizer_description_' . 'grandtotal') == '[AUTOMATIC]') {
         list($recurring, , $period, $occurrences) = $this->_itemsProps($this->_paymentBasket->loadPaymentItems());
         $renderedBasketPrice = $this->_paymentBasket->renderPrice(null, null, null, true);
         if ($recurring && ($this->_paymentBasket->period1 && $this->_paymentBasket->mc_amount1 != $this->_paymentBasket->mc_amount3)) {
             $then = $this->_paymentBasket->renderPrice($this->_paymentBasket->mc_amount3, $period, $occurrences, true);
             $renderedBasketPrice = sprintf(CBPTXT::Th("%s, then %s"), $renderedBasketPrice, $then);
         }
     } else {
         parent::renderColumn($variable, $output, $rounded);
     }
     return $renderedBasketPrice;
 }
	/**
	 * Returns substitution strings
	 *
	 * @see cbpaidSomething::substitutionStringsForItemDetailed()
	 *
	 * @param  boolean  $html           HTML or TEXT return
	 * @param  string   $reason         'N' new subscription, 'R' renewal, 'U'=update )
	 * @param  boolean  $autorecurring  TRUE: is autorecurring, no real expiration date, FALSE: is not autorecurring
	 * @return array
	 */
	public function substitutionStringsForItemDetailed( /** @noinspection PhpUnusedParameterInspection */ $html, $reason, $autorecurring ) {
		global $_CB_framework;

		$user						=	CBuser::getUserDataInstance( $this->user_id );

		$prefixText					=	'';

		$params						=&	cbpaidApp::settingsParams();

		$extraStrings				=	array(	'ITEM_NAME'				=>	$this->getPlan()->getPersonalized( 'name', $this->user_id, false ),		//	CBPTXT::T( $this->getText( 'name' ) ),
			'ITEM_ALIAS'			=>	CBPTXT::T( $this->getText( 'alias' ) ),
			'ITEM_DESCRIPTION'		=>	$this->getPlan()->getPersonalized( 'description', $this->user_id, false ),	//strip_tags( CBPTXT::T( $this->getText( 'description' ) ) ),
			'SITENAME'				=>	$_CB_framework->getCfg( 'sitename' ),
			'SITEURL'				=>	$_CB_framework->getCfg( 'live_site' ),
			'PLANS_TITLE'			=>	strip_tags( CBPTXT::T( $params->get( 'regTitle' ) ) ),
			'EMAILADDRESS'			=>	$user->email,
			'PREFIX_TEXT'			=>	$prefixText
		);
		return $extraStrings;
	}
 /**
  * Error Handling function of CBSubs to give as argument for set_error_handler
  * @deprecated : Use cbpaidErrorHandler::init() to set it.
  *
  * @param $errno
  * @param string $errstr
  * @param string $errfile
  * @param string $errline
  * @return bool
  */
 public static function _error_handler_callable($errno, $errstr = '', $errfile = '', $errline = '')
 {
     if (self::$handlerOff || defined('E_STRICT') && $errno == constant('E_STRICT')) {
         return false;
     }
     global $_CB_framework, $_CB_database;
     $cfg['adminEmail'] = null;
     // if error has been supressed with an @
     if (error_reporting() == 0) {
         return false;
     }
     // check if function has been called by an exception
     if (func_num_args() == 5) {
         // called by trigger_error()
         list($errno, $errstr, $errfile, $errline) = func_get_args();
         $backtrace = debug_backtrace();
     } else {
         // caught exception
         /** @var $exc Exception */
         $exc = func_get_arg(0);
         $errno = $exc->getCode();
         $errstr = $exc->getMessage();
         $errfile = $exc->getFile();
         $errline = $exc->getLine();
         $backtrace = array_reverse($exc->getTrace());
     }
     $errorType = array(E_ERROR => 'ERROR', E_WARNING => 'WARNING', E_PARSE => 'PARSING ERROR', E_NOTICE => 'NOTICE', E_CORE_ERROR => 'CORE ERROR', E_CORE_WARNING => 'CORE WARNING', E_COMPILE_ERROR => 'COMPILE ERROR', E_COMPILE_WARNING => 'COMPILE WARNING', E_USER_ERROR => 'USER ERROR', E_USER_WARNING => 'USER WARNING', E_USER_NOTICE => 'USER NOTICE');
     if (defined('E_STRICT')) {
         // php 5
         $errorType[E_STRICT] = 'STRICT NOTICE';
     }
     if (defined('E_RECOVERABLE_ERROR')) {
         // php 5.1.6 + 5.2.x
         $errorType[E_RECOVERABLE_ERROR] = 'E_RECOVERABLE_ERROR';
     }
     $errorPriority = array(E_ERROR => 1, E_WARNING => 4, E_PARSE => 1, E_NOTICE => 5, E_CORE_ERROR => 1, E_CORE_WARNING => 4, E_COMPILE_ERROR => 1, E_COMPILE_WARNING => 4, E_USER_ERROR => 1, E_USER_WARNING => 4, E_USER_NOTICE => 5);
     if (defined('E_STRICT')) {
         $errorPriority[E_STRICT] = 6;
     }
     if (defined('E_RECOVERABLE_ERROR')) {
         $errorPriority[E_RECOVERABLE_ERROR] = 6;
     }
     // create error message
     if (array_key_exists($errno, $errorType)) {
         $err = $errorType[$errno];
     } else {
         $err = 'CAUGHT EXCEPTION';
     }
     $errMsg = $err . ': ' . $errstr . ' in ' . $errfile . ' on line ' . $errline;
     // start backtrace:
     $trace = '';
     foreach ($backtrace as $v) {
         if (isset($v['class'])) {
             $trace .= 'called in class ' . $v['class'] . '::' . $v['function'] . '(';
             if (isset($v['args'])) {
                 $separator = '';
                 foreach ($v['args'] as $arg) {
                     $trace .= $separator . self::cbpaidGetArgument($arg);
                     $separator = ', ';
                 }
             }
             $trace .= ')';
             if (isset($v['line'])) {
                 $trace .= ' on line ' . $v['line'];
             }
             if (isset($v['file'])) {
                 $trace .= ' in file ' . substr(strrchr($v['file'], '/'), 1);
             }
         } elseif (isset($v['function'])) {
             if (strtolower($v['function']) != strtolower(__FUNCTION__)) {
                 $trace .= 'called in function ' . $v['function'] . '(';
                 if (!empty($v['args'])) {
                     $separator = '';
                     foreach ($v['args'] as $arg) {
                         $trace .= $separator . self::cbpaidGetArgument($arg);
                         $separator = ', ';
                     }
                 }
                 $trace .= ')';
                 if (isset($v['line'])) {
                     $trace .= ' on line ' . $v['line'];
                 }
                 if (isset($v['file'])) {
                     $trace .= ' in file ' . substr(strrchr($v['file'], '/'), 1);
                 }
             }
         } else {
             $trace .= '????';
             $trace .= '::::::' . var_export($v, true);
         }
         $trace .= "\n";
     }
     $trace .= '$_GET = ' . var_export($_GET, true) . "\n";
     $trace .= '$_POST = ' . var_export($_POST, true) . "\n";
     $errorText = $errMsg . "\n" . 'Trace:' . $trace . "\n";
     // display error msg, if debug is enabled
     if ($_CB_framework->getCfg('debug')) {
         if (defined('E_STRICT') && $errno != constant('E_STRICT')) {
             echo '<h2>CBPaid Debug Message</h2>' . nl2br($errMsg) . '<br />
 	        Trace:' . nl2br($trace) . '<br />';
         }
     }
     // what to do
     switch ($errno) {
         //    	case E_STRICT:	break;		// only if it's defined (php 4 compatibility)
         //        case E_NOTICE:
         //        case E_USER_NOTICE:
         //        	break;
         default:
             if (array_key_exists($errno, $errorPriority)) {
                 $priority = $errorPriority[$errno];
             } else {
                 $priority = 7;
             }
             $log = new cbpaidHistory($_CB_database);
             $errorTextForMe = strpos($errorText, 'cbpaidsubscriptions') !== false && strpos($errorText, 'parainvite') === false;
             if ($errorTextForMe) {
                 $log->logError($priority, $errorText, null);
             }
             if (TRUE || !$_CB_framework->getCfg('debug')) {
                 // send email to admin
                 if ($errorTextForMe && !empty($cfg['adminEmail'])) {
                     $params = cbpaidApp::settingsParams();
                     $licensee_name = $params->get('licensee_name');
                     @mail($cfg['adminEmail'], cbpaidApp::version() . ' error on ' . $_SERVER['HTTP_HOST'] . ' customer:' . $licensee_name, 'CBPaid Debug Message: ' . $errorText, 'From: error_handler');
                 }
                 if ($priority == 1) {
                     // end and display error msg
                     exit(self::cbDisplayClientMessage());
                 }
             } else {
                 exit('<p>aborting.</p>');
             }
             break;
     }
     return false;
 }
<?php

/**
* @version $Id: $
* @package CBSubs (TM) Community Builder Plugin for Paid Subscriptions (TM)
* @subpackage Template for Paid Subscriptions
* @copyright (C) 2007-2015 and Trademark of Lightning MultiCom SA, Switzerland - www.joomlapolis.com - and its licensors, all rights reserved
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
*/
/** ensure this file is being included by a parent file */
if (!(defined('_VALID_CB') || defined('_JEXEC') || defined('_VALID_MOS'))) {
    die('Direct Access to this location is not allowed.');
}
/** @noinspection PhpIncludeInspection */
include_once cbpaidApp::getAbsoluteFilePath('views/product.php');
/**
 * VIEW: User subscription view class
 *
 */
class cbpaidProductusersubscriptionView extends cbpaidProductView
{
    public $periodPrice;
    /**
     * Returns the version of the implemented View
     *
     * @return int
     */
    public function version()
    {
        return 1;
    }
	/**
	 * Get a correct display of the formatted validity of a plan
	 *
	 * @return string                     Formatted text giving validity of this subscription
	 */
	public function getFormattedValidityRemaining() {
		if ( ( $this->status == 'A' ) && ( $this->expiry_date == '0000-00-00 00:00:00' ) ) {
			$params				=&	cbpaidApp::settingsParams();
			return CBPTXT::T( $params->get( 'regtextLifetime', 'Lifetime Subscription' ) );
		} else {
			$occurrence			=	$this->regular_recurrings_used;
			if ( $occurrence > 0 ) {
				$reason			=	'R';
			} elseif ( $this->replaces_plan && $this->replaces_subscription ) {
				$reason			=	'U';
			} else {
				$reason			=	'N';
			}
			$varName			=	$this->getPlan()->getPlanVarName( $reason, $occurrence, 'validity' );
			return $this->getPlan()->getFormattedValidity( $this->getPlan()->strToTime( $this->expiry_date ), $this->getPlan()->strToTime( $this->subscription_date ), $varName );
		}
	}
	/**
	 * Maps array of arrays to an array of new objects of the corresponding class for each row
	 *
	 * @param  array|int      $resultsArray  array of a row of database to convert | int id of row to load
	 * @return cbpaidTable[]
	 */
	public function & getObjects( &$resultsArray ) {
		$objectsArray				=	array();
		if ( ! is_array( $resultsArray ) ) {
			$objectsArray[]			=	$this->getObject( $resultsArray );
		} else {
			foreach ( $resultsArray as $k => $value ) {
				$classSuffix		=	( isset( $value[$this->_classnameField] ) ? $value[$this->_classnameField] : '' );
				$lastDotPos			=	strrpos( $classSuffix, '.' );
				if ( $lastDotPos !== false ) {
					$classSuffix	=	substr( $classSuffix, $lastDotPos + 1 );
				}
				$class				=	$this->_classnamePrefix . ucfirst( $classSuffix );
				if ( ! class_exists( $class ) ) {
					// This is only needed during upgrade of 2.x to 3.x:
					if ( $this->_classLibrarySubfolders ) {
						// replace group.name by group.name.name , or name by name.name :
						$libName	=	preg_replace( '/^((.*)\.)*(.*)$/', '\1\3.\3', $value[$this->_classnameField] );
					} else {
						$libName	=	$value[$this->_classnameField];
					}
					cbpaidApp::import( $this->_classLibraryPrefix . $libName );
				}
				if ( class_exists( $class ) ) {

					// Now check case of abstract class for a new object to create:
					if ( ( ! isset( $value['id'] ) ) || ( $value['id'] == 0 ) || ( $value['id'] == '' ) ) {
						$reflection	=	new ReflectionClass( $class );
						if ( $reflection->isAbstract() ) {
							if ( class_exists( $class . 'Undefined' ) ) {
								$class		.=	'Undefined';
							} else {
								trigger_error( sprintf('%s:%s: Class %2s is abstract and cannot be instanciated and class %2sUndefined does not exist.', __CLASS__, __FUNCTION__, $class ), E_USER_ERROR );
							}
						}
					}

					// Ok, we can instanciate safely:
					$objectsArray[$k]	=	new $class( $this->_db );
					foreach ( $value as $kk => $vv ) {
						$objectsArray[$k]->$kk	=	$vv;
					}
				}
			}
		}
		return $objectsArray;
	}
 /**
  * Redirects expired user to the re-subscription screen.
  * @access private
  * @param  int  $userId
  */
 protected function _redirectExpiredMembership($userId)
 {
     global $_CB_framework;
     $params = cbpaidApp::settingsParams();
     $paidUserExtension = cbpaidUserExtension::getInstance($userId);
     $expiredSubscriptions = $paidUserExtension->getUserSubscriptions('X');
     // check if there is any expired extensions for the text
     if (count($expiredSubscriptions) > 0) {
         $textMessage = $params->get('subscriptionExpiredText', "Your membership has expired.");
         $expiredRedirectLink = $params->get('subscriptionExpiredRedirectLink');
     } else {
         $textMessage = $params->get('subscriptionNeededText', "A membership is needed for access.");
         $expiredRedirectLink = $params->get('subscriptionNeededRedirectLink');
     }
     if (!$expiredRedirectLink) {
         $baseClass = cbpaidApp::getBaseClass();
         if ($baseClass) {
             $expiredRedirectLink = $baseClass->_getAbsURLwithParam(array('Itemid' => 0, 'account' => 'expired', 'user' => (int) $userId), 'pluginclass', false);
         } else {
             // without baseClass, as baseClass is not loaded in case of cbpaidsubsbot:
             $cbpPrefix = 'cbp';
             $expiredRedirectLink = 'index.php?option=com_comprofiler&task=pluginclass&plugin=cbpaidsubscriptions&' . $cbpPrefix . 'account=expired&user='******'index.php?option=com_comprofiler&task=pluginclass&plugin=cbpaidsubscriptions&do=display_subscriptions';		// &Itemid= ???
         }
         if ($userId) {
             $_SESSION['cbsubs']['expireduser'] = $userId;
         }
     }
     if ($_CB_framework->getRequestVar('option') != 'com_comprofiler' || $_CB_framework->getRequestVar('task') != 'pluginclass' || $_CB_framework->getRequestVar('plugin') != 'cbpaidsubscriptions') {
         cbRedirect(cbSef($expiredRedirectLink, false), CBPTXT::T($textMessage), 'warning');
     }
 }
	/**
	 * USED by XML interface ONLY !!! Renders invoice
	 *
	 * @param  string           $value
	 * @param  ParamsInterface  $params
	 * @return string                    HTML to display
	 */
	public function renderInvoice( $value, &$params ) {
		global $_CB_framework;

		if ( ( $_CB_framework->getUi() == 2 ) && ( $_CB_framework->myId() != 0 ) ) {

			if ( cbpaidApp::getBaseClass() === null ) {
				//TODO: check if this is even needed:
				$pseudoPlugin				=	new getcbpaidsubscriptionsTab();
				$pseudoPlugin->params		=&	$params;
				cbpaidApp::getBaseClass( $pseudoPlugin );
			}
			$baseClass						=&	cbpaidApp::getBaseClass();

			$itsmyself					=	true;			// simulate user's view of invoice.

			$baseClass->outputRegTemplate();

			if ( strpos( cbGetParam( $_GET, 'invoice' ), ',') === false ) {
				if ( $this->load( (int) $value ) ) {
					$user					=	CBuser::getUserDataInstance( (int) $this->user_id );
				}
				return $this->displayInvoice( $user, $itsmyself, true );
			} else {
				$html					=	'<div class="cbregmultipage">';
				foreach ( explode( ',', cbGetParam( $_GET, 'invoice' ) ) as $basketId ) {
					$paymentBasket		=	new self();
					if ( $paymentBasket->load( (int) $basketId ) ) {
						$user			=	CBuser::getUserDataInstance( (int) $paymentBasket->user_id );
					}
					$html				.=	$paymentBasket->displayInvoice( $user, $itsmyself, false )
						.	'<hr class="cbregpagebreak" />';
					if ( is_callable( array( 'CBuser', 'unsetUsersNotNeeded' ) ) ) {
						// CB 1.8+:
						CBuser::unsetUsersNotNeeded( array( (int) $paymentBasket->user_id ) );
					}
					unset( $paymentBasket, $user );
				}
				$html					.=	'</div>';
			}
			return $html;
		}
		return null;
	}