/**
  * 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();
 }
예제 #2
0
	/**
	 * 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;
		}

	}
예제 #3
0
	/**
	 * 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;
		}
	}
 /**
  * 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;
     }
 }
	/**
	 * 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;
	}
예제 #10
0
	/**
	 * Renders a basket with content
	 *
	 * @param  string  $summaryText     Title         default: CBPTxt("Payment")
	 * @param  string  $captionText     Subtitle      default: CBPTxt("Your membership for payment:")
	 * @param  string  $displayColumnsParamsBaseName  'basket' or 'invoice'
	 * @param  string  $output                        'html' or ?
	 * @return string                                 HTML content with a table for the basket
	 */
	public function displayBasket( $summaryText = "Payment", $captionText = "Your membership for payment:", $displayColumnsParamsBaseName = 'basket', $output = 'html' ) {
		$return							=	null;

		$params							=&	cbpaidApp::settingsParams();

		$this->loadPaymentItems();
		$this->loadPaymentTotalizers();

		$displayColumns					=	 $this->_basketColumns( $displayColumnsParamsBaseName . '_item_line1_columns' );
		$totalizerColumns				=	 $this->_basketColumns( $displayColumnsParamsBaseName . '_totalizer_line1_columns' );

		// Now computes all basket items lines columns content, and removes completely emty columns:

		// this will hold 2-dimensional array of values in basket items view:
		$itemsLinesCols					=	array();
		foreach ( array_keys( $this->_paymentItems ) as $lineIdx ) {
			$itemsLinesCols[$lineIdx]['plan_cssclass']		=		$this->_paymentItems[$lineIdx]->getPlanParam( 'cssclass', '', null );
			foreach ( array_keys( $displayColumns ) as $colName ) {
				$itemsLinesCols[$lineIdx][$colName]		=	$this->renderBasketItem( $lineIdx, $colName, $output );
			}
		}
		if ( $params->get( $displayColumnsParamsBaseName . '_item_display_empty_columns', 0 ) == 0 ) {
			$this->_cleanUpEmptyColumns( $displayColumns, $itemsLinesCols );
		}

		$totalizerLinesCols				=	array();
		foreach ( array_keys( $this->_paymentTotalizers ) as $lineIdx ) {
			$totalizerLinesCols[$lineIdx]['totalizer_type']		=	$this->_paymentTotalizers[$lineIdx]->totalizer_type;
			foreach ( array_keys( $totalizerColumns ) as $colName ) {
				$totalizerLinesCols[$lineIdx][$colName]			=	$this->renderBasketTotalizer( $lineIdx, $colName, $output );
			}
		}
		if ( $params->get( $displayColumnsParamsBaseName . '_totalizer_display_empty_columns', 0 ) == 0 ) {
			$this->_cleanUpEmptyColumns( $totalizerColumns, $totalizerLinesCols );
		}


		if ( count( $this->_paymentTotalizers ) == 0 ) {
			// We have an old basket, that did not have totalizers: we still need to display it properly:
			if ( count ( $totalizerColumns ) == 0 ) {
				$totalizerColumns		=	array( 'description' =>	'Item', 'rate'	=>	'Price' );
			}
			$totalizerLinesCols			=	array();
			if ( ( (float) $this->tax ) != 0.0 ) {
				$renderedTotalNoTax		=	$this->renderTax( $this->mc_gross - $this->tax, true );
				$renderedTaxAmount		=	$this->renderTax( $this->tax, true );

				$totalizerLinesCols[]	=	array( 'totalizer_type' => 'subtotal1', 'description' =>	CBPTXT::Th("Total before tax"), 'rate'	=>	$renderedTotalNoTax );
				$totalizerLinesCols[]	=	array( 'totalizer_type' => 'salestax', 'description' => CBPTXT::Th("Sales tax"), 'rate'	=>	$renderedTaxAmount );
			}
			$renderedBasketPrice		=	$this->renderPrice( null, null, null, true );
			$totalizerLinesCols[]		=	array( 'totalizer_type' => 'grandtotal', 'description' => CBPTXT::Th("Total"), 'rate'	=>	$renderedBasketPrice );
		}

		$subscriptionsGUI				=	new cbpaidControllerUI();
		$return							=	$subscriptionsGUI->showBasket( $this, $summaryText, $captionText, $displayColumns, $totalizerColumns, $itemsLinesCols, $totalizerLinesCols );

		return $return;
	}
 /**
  * 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;
 }
예제 #12
0
	/**
	 * Constructor
	 * @private
	 */
	protected function __construct( ) {
		$this->params					=&	cbpaidApp::settingsParams();
	}
 /**
  * Override Core method to load parameters to plugin: use #__cbsubs_config instead of params column of comprofiler_plugin
  *
  * @param  int|null  $pluginid
  * @param  string    $extraParams  Extra parameters (e.g. from the tab settings)
  */
 public function _loadParams($pluginid, $extraParams = null)
 {
     $this->params = cbpaidApp::settingsParams();
     /*
     		global $_CB_database;
     
     		static $_params			=	null;
     
     		// $this->params		=	new Registry( $_PLUGINS->_plugins[$pluginid]->params . "\n" . $extraParams );
     		if ( $_params === null ) {
     			$_params			=	new cbpaidConfig( $_CB_database );
     			if ( $_params->load( 1 ) ) {
     				$_params		=	new Registry( $_params->params . "\n" . $extraParams );
     			} else {
     				$_params		=	new Registry( $extraParams );
     			}
     		}
     		$this->params			=	$_params;
     */
 }
예제 #14
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;
	}
	/**
	 * Constructor
	 */
	public function __construct( ) {
		$this->params	=	cbpaidApp::settingsParams();
		$this->base		=	cbpaidApp::getBaseClass();

	}
예제 #16
0
	/**
	 * Get a correct display of the formatted validity of a plan: override if needed
	 *
	 * @return string                     Formatted text giving validity of this subscription
	 */
	public function getFormattedExpirationDateText() {
		if ( $this->status == 'A' ) {
			$params				=&	cbpaidApp::settingsParams();
			return CBPTXT::T( $params->get( 'regtextLifetime', 'Lifetime Subscription' ) );
		} else {
			return CBPTXT::T('Not active');
		}
	}
 /**
  * Updates payment status of basket and of corresponding subscriptions if there is a change in status
  *
  * @param  cbpaidPaymentBasket        $paymentBasket         Basket
  * @param  string                     $eventType             type of event (paypal type): 'web_accept', 'subscr_payment', 'subscr_signup', 'subscr_modify', 'subscr_eot', 'subscr_cancel', 'subscr_failed'
  * @param  string                     $paymentStatus         new status (Completed, RegistrationCancelled)
  * @param  cbpaidPaymentNotification  $notification          notification object of the payment
  * @param  int                        $occurrences           renewal occurrences
  * @param  int                        $autorecurring_type    0: not auto-recurring, 1: auto-recurring without payment processor notifications, 2: auto-renewing with processor notifications updating $expiry_date
  * @param  int                        $autorenew_type        0: not auto-renewing (manual renewals), 1: asked for by user, 2: mandatory by configuration
  * @param  boolean|string             $txnIdMultiplePaymentDates  FALSE: unique txn_id for each payment, TRUE: same txn_id can have multiple payment dates, additionally: 'SINGLEPAYMENT' will not look at txn_id at all
  * @param  boolean                    $storePaymentRecord   TRUE: normal case, create payment record if needed. FALSE: offline case where pending payment should not create a payment record.
  * @return void
  */
 public function updatePaymentStatus($paymentBasket, $eventType, $paymentStatus, &$notification, $occurrences, $autorecurring_type, $autorenew_type, $txnIdMultiplePaymentDates, $storePaymentRecord = true)
 {
     global $_CB_framework, $_PLUGINS;
     $pluginsLoaded = false;
     $basketUpdateNulls = false;
     $previousUnifiedStatus = $this->mapPaymentStatus($paymentBasket->payment_status);
     $unifiedStatus = $this->mapPaymentStatus($paymentStatus);
     // get all related subscriptions being paid by this basket:
     $subscriptions = $paymentBasket->getSubscriptions();
     $thisIsReferencePayment = false;
     $user = CBuser::getUserDataInstance((int) $paymentBasket->user_id);
     if ($paymentBasket->payment_status != $paymentStatus || $unifiedStatus == 'Partially-Refunded' || $autorecurring_type) {
         if ($paymentStatus && (in_array($eventType, array('web_accept', 'subscr_payment', 'subscr_signup')) || in_array($unifiedStatus, array('Reversed', 'Refunded', 'Partially-Refunded')))) {
             $paymentBasket->payment_status = $paymentStatus;
         }
         if (in_array($eventType, array('subscr_payment', 'subscr_signup'))) {
             $paymentBasket->recurring = 1;
         }
         if ($autorecurring_type == 0 && in_array($unifiedStatus, array('Completed', 'Processed', 'FreeTrial'))) {
             $paymentBasket->mc_amount1 = null;
             $paymentBasket->mc_amount3 = null;
             $paymentBasket->period1 = null;
             $paymentBasket->period3 = null;
             $basketUpdateNulls = true;
         }
         // if (count($subscriptions) >= 1) {
         $now = $_CB_framework->now();
         $completed = false;
         $thisIsReferencePayment = false;
         $reason = null;
         switch ($unifiedStatus) {
             case 'FreeTrial':
             case 'Completed':
             case 'Processed':
                 // this includes Canceled_Reversal !!! :
                 if ($unifiedStatus == 'FreeTrial') {
                     $paymentBasket->payment_status = 'Completed';
                 }
                 if ($unifiedStatus == 'FreeTrial' || $unifiedStatus == 'Completed') {
                     if ($notification->payment_date) {
                         $time_completed = cbpaidTimes::getInstance()->gmStrToTime($notification->payment_date);
                     } else {
                         $time_completed = $now;
                     }
                     $paymentBasket->time_completed = Application::Database()->getUtcDateTime($time_completed);
                     $completed = true;
                 }
                 if ($paymentStatus == 'Canceled_Reversal') {
                     $paymentBasket->payment_status = 'Completed';
                 }
                 if (is_object($notification) && isset($notification->txn_id)) {
                     // real payment with transaction id: store as reference payment if not already stored:
                     $thisIsReferencePayment = $this->_storePaymentOnce($paymentBasket, $notification, $now, $txnIdMultiplePaymentDates, 'Updating payment record because of new status of payment basket: ' . $unifiedStatus . ($paymentStatus != $unifiedStatus ? ' (new gateway-status: ' . $paymentStatus . ')' : '') . ' because of event received: ' . $eventType . '. Previous status was: ' . $previousUnifiedStatus);
                 } else {
                     // Free trials don't have a notification:
                     $thisIsReferencePayment = true;
                 }
                 if ($thisIsReferencePayment) {
                     // payment not yet processed:
                     $autorenewed = $paymentBasket->recurring == 1 && $unifiedStatus == 'Completed' && $previousUnifiedStatus == 'Completed';
                     for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
                         $reason = $autorenewed ? 'R' : $subscriptions[$i]->_reason;
                         $subscriptions[$i]->activate($user, $now, $completed, $reason, $occurrences, $autorecurring_type, $autorenew_type, $autorenewed ? 1 : 0);
                     }
                 }
                 break;
             case 'RegistrationCancelled':
             case 'Reversed':
             case 'Refunded':
             case 'Unsubscribed':
                 if ($unifiedStatus == 'RegistrationCancelled') {
                     if (!($previousUnifiedStatus == 'NotInitiated' || $previousUnifiedStatus === 'Pending' && $paymentBasket->payment_method === 'offline')) {
                         return;
                     }
                 }
                 for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
                     $reason = $subscriptions[$i]->_reason;
                     if ($reason != 'R' || in_array($unifiedStatus, array('Reversed', 'Refunded'))) {
                         // Expired and Cancelled as well as Partially-Refunded are not reverted !		//TBD: really revert on refund everything ? a plan param would be nice here
                         if (!in_array($previousUnifiedStatus, array('Pending', 'In-Progress', 'Denied', 'Reversed', 'Refunded')) && in_array($subscriptions[$i]->status, array('A', 'R', 'I')) && !$subscriptions[$i]->hasPendingPayment($paymentBasket->id)) {
                             // not a cancelled or denied renewal:
                             $subscriptions[$i]->revert($user, $unifiedStatus);
                         }
                     }
                 }
                 if ($unifiedStatus == 'RegistrationCancelled') {
                     $paymentBasket->historySetMessage('Payment basket deleted because the subscriptions and payment got cancelled');
                     $paymentBasket->delete();
                     // deletes also payment_Items
                 }
                 $paidUserExtension = cbpaidUserExtension::getInstance($paymentBasket->user_id);
                 $subscriptionsAnyAtAll = $paidUserExtension->getUserSubscriptions('');
                 $params = cbpaidApp::settingsParams();
                 $createAlsoFreeSubscriptions = $params->get('createAlsoFreeSubscriptions', 0);
                 if (count($subscriptionsAnyAtAll) == 0 && !$createAlsoFreeSubscriptions) {
                     $user = new UserTable();
                     $id = (int) cbGetParam($_GET, 'user');
                     $user->load((int) $id);
                     if ($user->id && $user->block == 1) {
                         $user->delete(null);
                     }
                 }
                 break;
             case 'Denied':
             case 'Pending':
                 if ($unifiedStatus == 'Denied') {
                     // In fact when denied, it's the case as if the user attempted payment but failed it: He should be able to re-try: So just store the payment as denied for the records.
                     if ($eventType == 'subscr_failed' || $eventType == 'subscr_cancel' && $autorecurring_type != 2) {
                         // special case of a failed attempt:
                         // or this is the final failed attempt of a basket with notifications:
                         break;
                     }
                 }
                 if ($previousUnifiedStatus == 'Completed') {
                     return;
                     // do not change a Completed payment as it cannot become Pending again. If we get "Pending" after "Completed", it is a messages chronological order mistake.
                 }
                 break;
             case 'In-Progress':
             case 'Partially-Refunded':
             default:
                 break;
         }
         if ($eventType == 'subscr_cancel') {
             if (!in_array($unifiedStatus, array('Denied', 'Reversed', 'Refunded', 'Unsubscribed'))) {
                 for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
                     $subscriptions[$i]->autorecurring_cancelled($user, $unifiedStatus, $eventType);
                 }
             }
         }
         for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
             $subscriptions[$i]->notifyPaymentStatus($unifiedStatus, $previousUnifiedStatus, $paymentBasket, $notification, $now, $user, $eventType, $paymentStatus, $occurrences, $autorecurring_type, $autorenew_type);
         }
         if (in_array($unifiedStatus, array('Denied', 'Reversed', 'Refunded', 'Partially-Refunded', 'Pending', 'In-Progress'))) {
             $thisIsReferencePayment = $this->_storePaymentOnce($paymentBasket, $notification, $now, $txnIdMultiplePaymentDates, 'Updating payment record because of new status of payment basket: ' . $unifiedStatus . ($paymentStatus != $unifiedStatus ? ' (new gateway-status: ' . $paymentStatus . ')' : '') . ' because of event received: ' . $eventType . '. Previous status was: ' . $previousUnifiedStatus);
         }
         // }
         foreach ($paymentBasket->loadPaymentTotalizers() as $totalizer) {
             $totalizer->notifyPaymentStatus($thisIsReferencePayment, $unifiedStatus, $previousUnifiedStatus, $paymentBasket, $notification, $now, $user, $eventType, $paymentStatus, $occurrences, $autorecurring_type, $autorenew_type, $txnIdMultiplePaymentDates);
         }
         if (!in_array($unifiedStatus, array('RegistrationCancelled'))) {
             if ($thisIsReferencePayment && in_array($unifiedStatus, array('Completed', 'Processed'))) {
                 $paymentBasket->setPaidInvoiceNumber($reason);
             }
             $paymentBasket->historySetMessage('Updating payment basket ' . ($paymentStatus !== null ? 'status: ' . $unifiedStatus . ($paymentStatus != $unifiedStatus ? ' (new gateway-status: ' . $paymentStatus . ')' : '') : '') . ' because of event received: ' . $eventType . ($paymentStatus !== null ? '. Previous status was: ' . $previousUnifiedStatus : ''));
             $paymentBasket->store($basketUpdateNulls);
         } else {
             //TDB ? : $paymentBasket->delete(); in case of RegistrationCancelled done above, but should be done in case of FreeTrial ? (could be a param in future)
         }
         if (!in_array($unifiedStatus, array('Completed', 'Processed')) || $thisIsReferencePayment) {
             $_PLUGINS->loadPluginGroup('user', 'cbsubs.');
             $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin');
             $pluginsLoaded = true;
             $_PLUGINS->trigger('onCPayAfterPaymentStatusChange', array(&$user, &$paymentBasket, &$subscriptions, $unifiedStatus, $previousUnifiedStatus, $occurrences, $autorecurring_type, $autorenew_type));
         }
     }
     if (!in_array($unifiedStatus, array('Completed', 'Processed')) || $thisIsReferencePayment) {
         if (!$pluginsLoaded) {
             $_PLUGINS->loadPluginGroup('user', 'cbsubs.');
             $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin');
         }
         $_PLUGINS->trigger('onCPayAfterPaymentStatusUpdateEvent', array(&$user, &$paymentBasket, &$subscriptions, $unifiedStatus, $previousUnifiedStatus, $eventType, &$notification));
     }
 }
 /**
  * Draws a subscription's name and description...
  *
  * @param  int|null $now                     unix time for the expiration times (null: now)
  * @param  string   $insertAfterDescription  HTML text to insert after this item as sub-items
  * @param  boolean  $showStateCheckMark
  * @return string
  */
 public function drawSomethingNameDescription($now, $insertAfterDescription, $showStateCheckMark = true)
 {
     global $_CB_framework, $_PLUGINS;
     /** @var $subscription cbpaidUsersubscriptionRecord */
     $subscription = $this->_model;
     $params = cbpaidApp::settingsParams();
     $showtime = $params->get('showtime', '1') == '1';
     $subTxt = CBPTXT::T($params->get('subscription_name', 'subscription'));
     $titlesTexts = array('A' => sprintf(CBPTXT::T("Active %s"), $subTxt), 'AA' => sprintf(CBPTXT::T("Active %s"), $subTxt), 'R' => sprintf(CBPTXT::T("%s not yet paid"), ucfirst($subTxt)), 'U' => sprintf(CBPTXT::T("Upgraded %s"), $subTxt), 'C' => sprintf(CBPTXT::T("Unsubscribed %s"), $subTxt), 'X' => sprintf(CBPTXT::T("Expired %s"), $subTxt), 'XX' => sprintf(CBPTXT::T("Inactive (parent %s not active)"), $subTxt), 'ZZ' => sprintf(CBPTXT::T("Unknown state of %s"), $subTxt));
     // local state
     //TODO use getFormattedExpirationDateText()
     $stateTexts = array('A' => CBPTXT::T("Active"), 'AA' => CBPTXT::T("Active, expiring on %s"), 'R' => CBPTXT::T("Not yet paid"), 'U' => CBPTXT::T("Upgraded to higher plan on %s"), 'C' => CBPTXT::T("Unsubscribed on %s"), 'X' => CBPTXT::T("Expired %s"), 'XX' => sprintf(CBPTXT::T("Inactive (parent %s not active)"), $subTxt), 'ZZ' => sprintf(CBPTXT::T("Unknown state of %s"), $subTxt));
     // local state
     $autoRenewingText = CBPTXT::T("%s, auto-renewing");
     $autoRenewingXtimes = CBPTXT::T("%s, auto-renewing %s more times until %s");
     // check if active and if parents are active:
     $realStatus = $subscription->realStatus($now);
     $subActive = $subscription->checkIfValid($now);
     $subAndParentsActive = $subscription->checkIfThisAndParentSubscriptionIsValid($now);
     if ($subActive && !$subAndParentsActive) {
         $status = 'XX';
     } else {
         // compute local pseudo status, which is subscription status and 2 local states: AA and ZZ:
         $status = $realStatus;
         if (!array_key_exists($realStatus, $titlesTexts)) {
             $status = 'ZZ';
         }
         if ($status == 'A' && !$subscription->isLifetimeValidity()) {
             $status = 'AA';
         }
     }
     if ($status == 'ZZ' && $_CB_framework->getUi() == 1) {
         // if status is unknown, don't display it in frontend, only in backend !
         return $insertAfterDescription;
     }
     $viewModel = new cbpaidSomethingViewModel();
     $viewModel->subscription = $subscription;
     $viewModel->name = $subscription->getPlan()->getPersonalized('name', $subscription->user_id, true);
     $viewModel->description = $subscription->getPlan()->getPersonalized('description', $subscription->user_id, true);
     $viewModel->cssclass = $subscription->getPlanAttribute('cssclass');
     $viewModel->active = $subAndParentsActive;
     $viewModel->validity = htmlspecialchars($subscription->getFormattedValidityRemaining());
     $viewModel->title = htmlspecialchars($titlesTexts[$status]);
     // Prepare the exact description text for the status:
     if ($subscription->expiry_date && !($subscription->status == 'X' && $subActive)) {
         $expDate = cbFormatDate($subscription->expiry_date, 1, $showtime);
     } else {
         $expDate = '';
     }
     $stateText = sprintf($stateTexts[$status], $expDate);
     // add information of auto-renewals if autorecurring and all autorecurrings are not yet done:
     if ($subscription->autorecurring_type > 0 && $status == 'AA' && ($subscription->regular_recurrings_total == 0 || $subscription->regular_recurrings_used < $subscription->regular_recurrings_total)) {
         if ($subscription->autorecurring_type == 2 && $subscription->regular_recurrings_total && $subscription->regular_recurrings_used < $subscription->regular_recurrings_total) {
             $occurrences = $subscription->regular_recurrings_total - $subscription->regular_recurrings_used;
             $finalExpTime = $subscription->computeExpiryTimeIfActivatedNow($now, 'R', $occurrences);
             $finalExpTxt = cbFormatDate($finalExpTime, 1, $showtime);
             // '%s, auto-renewing %s more times until %s' :
             $stateText = sprintf($autoRenewingXtimes, $stateText, $occurrences, $finalExpTxt);
         } else {
             // '%s, auto-renewing' :
             $stateText = sprintf($autoRenewingText, $stateText);
         }
     }
     $viewModel->stateText = htmlspecialchars($stateText);
     //TBD ???? $plan->displayPeriodPrice( 'R', $sub->getOccurrence() + 1, null, $plan->strToTime( $sub->expiry_date ), false );
     $_PLUGINS->loadPluginGroup('user', 'cbsubs.');
     $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin');
     $insertBeforeValidity = implode('', $_PLUGINS->trigger('onCPayBeforeDrawSubscription', array(&$viewModel, &$subscription, &$insertAfterDescription)));
     /** @var $view cbpaidsomethingusersubscriptionView */
     $view = cbpaidTemplateHandler::getViewer($this->templateToUse(), 'somethingusersubscription', 'html');
     //TBD extend to any Something (merchandises, donations)
     $view->setModel($viewModel);
     return $view->drawSomething($insertBeforeValidity, $insertAfterDescription, $showStateCheckMark);
 }
 /**
  * Computes user's ACL and block depending on list of subscriptions.
  *
  * @param  UserTable                       $user
  * @param  cbpaidUsersubscriptionRecord[]  $subscriptions
  * @return array                                           ( $block, $gids, $allGids )
  */
 public function _computeMaxBlockGid($user, &$subscriptions)
 {
     global $_CB_framework;
     $params = cbpaidApp::settingsParams();
     $enableFreeRegisteredUser = $params->get('enableFreeRegisteredUser', 1);
     // Determine highest new $gid (0 means nothing left):
     $registeredGid = (int) $_CB_framework->getCfg('new_usertype');
     if (!in_array($registeredGid, (array) $user->gids)) {
         $registeredGid = (int) $_CB_framework->acl->mapGroupNamesToValues('Registered');
     }
     $gids = array($registeredGid);
     // default minimum acl gid
     $allGids = array($registeredGid);
     $block = 0;
     // don't block by default
     if (count($subscriptions)) {
         $activeGids = array();
         foreach ($subscriptions as $sub) {
             $subGid = (int) $sub->getPlanAttribute('usergroup');
             if ($subGid) {
                 $activeGids[$subGid] = $subGid;
             }
         }
         if (count($activeGids) > 0) {
             $activeGids[$registeredGid] = $registeredGid;
             $gids = array_values($activeGids);
             $allGids = $gids;
         }
     } elseif (!$enableFreeRegisteredUser && !in_array($_CB_framework->acl->mapGroupNamesToValues('Superadministrator'), (array) $user->gids)) {
         $block = 1;
     }
     return array($block, $gids, $allGids);
 }
예제 #20
0
	/**
	* 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 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 );
	}
	/**
	 * 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;
	}
 /**
  * View for <param  type="private" class="cbpaidParamsExt" method="lastlicensestate">...
  *
  * @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 configstatetext($value, &$pluginParams, $name, &$param, $control_name, $control_name_name, $view, &$modelOfData, &$modelOfDataRows, &$modelOfDataRowsNumber)
 {
     $lastSavedVersion = cbpaidApp::settingsParams()->get('lastsavedversion');
     if ($lastSavedVersion === cbpaidApp::version()) {
         return null;
     } elseif ($lastSavedVersion) {
         return '<span class="cbDisabled">' . CBPTXT::Th("Not yet saved with this version") . '</span>';
     } else {
         return '<span class="cbDisabled">' . CBPTXT::Th("Settings not yet set") . '</span>';
     }
 }
	/**
	 * display basket and payment buttons or redirect for payment depending if multiple payment choices or intro text present:
	 *
	 * @param  UserTable            $user
	 * @param  cbpaidPaymentBasket  $paymentBasket
	 * @param  string               $introText
	 * @param  boolean              $ajax           TRUE if AJAX refresh inside #cbregPayMethodsChoice, FALSE: wraps in <div id="cbregPayMethodsChoice">
	 * @return string                               HTML  (or DOES REDIRECT if $redirectNow = ! ( ( $nbClasses != 1 ) || $introText ) == TRUE)
	 */
	public function getPaymentBasketPaymentForm( &$user, &$paymentBasket, $introText, $ajax = false ) {
		global $_PLUGINS;

		$result								=	null;

		$params								=	cbpaidApp::settingsParams();
		$invoicingAddressQuery				=	$params->get( 'invoicing_address_query' );
		$basket_requiredterms				=	$params->get( 'basket_requiredterms' );
		$basket_requiredtermserror			=	$params->get( 'basket_requiredtermserror' );
		$payment_method_selection_type		=	$params->get( 'payment_method_selection_type', 'buttons' );
		$allow_select_currency				=	$params->get( 'allow_select_currency', '0' );

		$redirectNow						=	null;
		$payChoicesArray					=	$this->getPaymentMethodsParams( $user, $paymentBasket, $introText, $redirectNow );

		$chosenPaymentMethod				=	$paymentBasket->gateway_account ? $paymentBasket->gateway_account . '-' . $paymentBasket->payment_type : '';		// cbGetParam( $_POST, 'payment_method' );

		$payChoicesHtmlRadiosArray			=	array();
		$chosenPaymentSelector				=	null;
		$payChoicesHtmlBottomArray			=	$this->_renderPayChoicesArray( $payChoicesArray, $paymentBasket, $redirectNow, $chosenPaymentMethod, $payChoicesHtmlRadiosArray, $chosenPaymentSelector );
		if ( $redirectNow == 'redirect' && is_string( $payChoicesHtmlBottomArray ) ) {
			cbRedirect( $payChoicesHtmlBottomArray );
		}

		$subscriptionsGUI					=	new cbpaidControllerUI();
		$subscriptionsGUI->addcbpaidjsplugin();

		if ( ( $payment_method_selection_type == 'radios') && ( $chosenPaymentMethod != '' ) && $chosenPaymentSelector ) {
			// Select button to draw:
			$payChoicePayButton				=	$this->getPayMethodButton( $user, $paymentBasket, $paymentBasket->gateway_account, $paymentBasket->payment_type, $chosenPaymentSelector );
			/** @var $chosenPaymentSelector cbpaidGatewaySelector */
			$this->modifyAspectPayMethodButton( $payChoicePayButton, $chosenPaymentSelector->paymentType );
			$dummy							=	null;
			$payChoicePayButtonHtmlArray	=	$this->_renderPayChoicesArray( array( $payChoicePayButton ), $paymentBasket, 'buttons', $chosenPaymentMethod, $payChoicesHtmlRadiosArray, $dummy );
			$payChoicesHtmlBottomArray		=	array_merge( $payChoicesHtmlBottomArray, $payChoicePayButtonHtmlArray );
		}

		if ( true )  {
			// always add cancel link
			cbpaidApp::import( 'processors.cancelpay.cancelpay' );
			$cancelmethod					=	new cbpaidGatewayAccountcancelpay();
			$payClass						=	$cancelmethod->getPayMean();
			$payChoicesHtmlBottomArray[]	=	$payClass->getPaymentBasketProcess( $user, $paymentBasket, 'buttons' );	// never redirectNow a cancel link :D !
		}

		$basketHtml							=	$paymentBasket->displayBasket();

		if ( $allow_select_currency == 2 ) {
			$currencySelector				=	$this->displayCurrencySelector( $paymentBasket );
		} else {
			$currencySelector				=	null;
		}
		$txtConclusion						=	$params->get('conclusion_text');
		$txtFinal							=	$params->get('final_text');

		$txtTerms						=	null;
		if ( $basket_requiredterms == 1 ) {
			global $_CB_database, $_CB_framework;

			$query							=	'SELECT ' . $_CB_database->NameQuote( 'params' )
											.	"\n FROM " .  $_CB_database->NameQuote( '#__comprofiler_fields' )
											.	"\n WHERE " . $_CB_database->NameQuote( 'name' ) . " = " . $_CB_database->Quote( 'acceptedterms' );
			$_CB_database->setQuery( $query );
			$tcParams						=	new Registry( $_CB_database->loadResult() );

			$termsOutput					=	$tcParams->get( 'terms_output', 'url' );
			$termsDisplay					=	$tcParams->get( 'terms_display', 'modal' );
			$termsURL						=	$tcParams->get( 'terms_url', null );
			$termsText						=	$tcParams->get( 'terms_text', null );
			$termsWidth						=	(int) $tcParams->get( 'terms_width', 400 );
			$termsHeight					=	(int) $tcParams->get( 'terms_height', 200 );

			if ( ! $termsHeight ) {
				$termsHeight				=	200;
			}

			if ( ( ( $termsOutput == 'url' ) && $termsURL ) || ( ( $termsOutput == 'text' ) && $termsText ) ) {
				if ( $termsDisplay == 'iframe' ) {
					if ( $termsOutput == 'url' ) {
						$txtTerms			.=				'<iframe class="cbTermsFrameURL" height="' . $termsHeight . '" width="' . ( $termsWidth ? $termsWidth : '100%' ) . '" src="' . htmlspecialchars( $termsURL ) . '"></iframe>';
					} else {
						$txtTerms			.=				'<div class="cbTermsFrameText" style="height:' . $termsHeight . 'px;width:' . ( $termsWidth ? $termsWidth . 'px' : '100%' ) . ';overflow:auto;">' . CBPTXT::T( $termsText ) . '</div>';
					}
				}

				if ( $termsDisplay != 'iframe' ) {
					$attributes				=	' class="cbTermsLink"';

					if ( ( $termsOutput == 'text' ) && ( $termsDisplay == 'window' ) ) {
						$termsDisplay		=	'modal';
					}

					if ( $termsDisplay == 'modal' ) {
						if ( ! $termsWidth ) {
							$termsWidth		=	400;
						}

						if ( $termsOutput == 'url' ) {
							$tooltip		=	'<iframe class="cbTermsModalURL" height="' . $termsHeight . '" width="' . $termsWidth . '" src="' . htmlspecialchars( $termsURL ) . '"></iframe>';
						} else {
							$tooltip		=	'<div class="cbTermsModalText" style="height:' . $termsHeight . 'px;width:' . $termsWidth . 'px;overflow:auto;">' . CBPTXT::T( $termsText ) . '</div>';
						}

						$url				=	'javascript:void(0);';
						$attributes			.=	' ' . cbTooltip( $_CB_framework->getUi(), $tooltip, CBPTXT::T( 'Terms and Conditions' ), 'auto', null, null, null, 'data-cbtooltip="true" data-modal="true"' );
					} else {
						$url				=	htmlspecialchars( $termsURL );
						$attributes			.=	' target="_blank"';
					}

					$txtTerms				.=				CBPTXT::P( 'I have read and approve the <a href="[url]"[attributes]>Terms and Conditions</a>', array( '[url]' => $url, '[attributes]' => $attributes ) );
				} else {
					$txtTerms				.=				CBPTXT::T( 'I have read and approve the above Terms and Conditions.' );
				}
			}
		} elseif ( $basket_requiredterms == 2 ) {
			$txtTerms					=	$params->get( 'basket_termsandconditions' );
		}

		if ($introText) {
			$result						.=	'<div class="cbregIntro">' . CBPTXT::Th( $introText ) . "</div>\n";
		}
		$result							.=	$basketHtml;

		if ( $allow_select_currency == 2 ) {
			$result						.=	$currencySelector;
		}

		if ( $invoicingAddressQuery > 0 ) {
			$errorMsg					=	$paymentBasket->checkAddressComplete();
			if ( $errorMsg && ( $invoicingAddressQuery == 2 ) ) {
				$result					=	'';
				$introAddrNeeded		=	$params->get('invoicing_address_required_into_text');
				if ($introAddrNeeded) {
					$result				.=	'<div class="cbregIntro">' . CBPTXT::Th( $introAddrNeeded ) . "</div>\n";
				}
				$result					.=	$paymentBasket->renderInvoicingAddressForm( $user );	// $xmlController->handleAction( 'action', 'editinvoiceaddress' );
				return $result;
			} else {
				if ( $errorMsg ) {
					cbpaidApp::getBaseClass()->_setErrorMSG( $errorMsg );
				}
				$result					.=	'<div class="cbregInvoicingAddress">'
					.	$paymentBasket->renderInvoicingAddressFieldset()
					.	'</div>';
			}
			// display current invoicing address with a link to change/edit it with a back link to the payment basket id
			// if the address is not mandatory.
			// If it is mandatory, check that it is complete (and later also screened),
			// if not display instead of this the invoicing address edit page !
		}
		$integrationsResults			=	$_PLUGINS->trigger( 'onCbSubsAfterPaymentBasket', array( $paymentBasket, &$result, &$txtTerms ) );
		foreach ( $integrationsResults as $intRes ) {
			if ( is_string( $intRes ) ) {
				$result					.=	$intRes;
			}
		}
		if ( $txtConclusion ) {
			$result						.=	'<div class="cbregConcl">' . CBPTXT::Th( $txtConclusion ) . "</div>\n";
		}

		if ( count( $payChoicesHtmlRadiosArray ) > 0 ) {

			$radios_intro_html			=	CBPTXT::Th( $params->get( 'radios_intro_html' ) );
			$radios_conclusion_html		=	CBPTXT::Th( $params->get( ( $chosenPaymentMethod != null ) ? 'radios_selected_conclusion_html' : 'radios_unselected_conclusion_html' ) );

			$htmlList					=	'<ul class="cbregPaymentMethodChoiceList">' . "\n";
			foreach ( $payChoicesHtmlRadiosArray as $selHtmlArr ) {
				if ( $selHtmlArr[0] ) {
					$htmlList			.=	'<li class="cbregCCradioLi cbregCCradioSelected">';
				} else {
					$htmlList			.=	'<li class="cbregCCradioLi">';				//LATER:  class="cbpaidCCradio cbpaidRadio_<?php echo htmlspecialchars( $this->payNameForCssClass ); " id="<?php echo htmlspecialchars( $this->butId );
				}
				$htmlList				.=	'<div class="cbregCCradioLiBg"></div>'		// This allows to use the CSS trick for highlighting as explained here: http://www.commentcamarche.net/forum/affich-3898635-transparance-du-fond-uniquement
					.	$selHtmlArr[1]
					.	"</li>\n";
			}
			$htmlList					.=	"</ul>\n";

			$methodsHTML				=	'<div class="cbregPaymentMethodChoice ' . ( ( $chosenPaymentMethod != null ) ? 'cbregPMselected' : 'cbregPMunselected' ) . '">'
				.	( $radios_intro_html ? '<h2 class="contentheading cbregPaymenMethodChoiceIntro">' . $radios_intro_html . '</h2>' : '' )
				.	$htmlList
				.	'<span class="cb_button_wrapper">'
				.	'<button type="submit" id="cbregSelectPayment">' . CBPTXT::Th("Change Payment Method") . '</button>'
				.	'</span>'
				.	( $radios_conclusion_html ? '<div class="cbregPaymenMethodChoiceConclusion">' . $radios_conclusion_html . '</div>' : '' )
				.	"</div>\n"
			;
			$getParams					=	$paymentBasket->getSetBasketPaymentMethodUrl( $user );
			$ajaxGetParams				=	cbUnHtmlspecialchars( $paymentBasket->getSetBasketPaymentMethodUrl( $user, 'raw' ) );
			$formHiddens				=	array(	cbpaidApp::getBaseClass()->_getPagingParamName('act') => 'setbsktpmtmeth',
				'ajaxurl' => bin2hex( $ajaxGetParams ) );
			$result						.=	'<div class="cbregPaymentMethodsSelect">' . $subscriptionsGUI->drawForm( $methodsHTML, null, $formHiddens, $getParams ) . "</div>\n";
			$termsCanBeDisplayed		=	( $payment_method_selection_type != 'radios' ) || ( $chosenPaymentMethod != null );
		} else {
			$termsCanBeDisplayed		=	true;
		}

		if ( $txtTerms ) {
			if ( $termsCanBeDisplayed ) {
				$accepted				=	( cbGetParam( $_POST, 'terms_accepted', 0 ) == 1 );
				$settings				=	'<div class="cbregTermsAccept"><input type="checkbox" class="required" name="terms_accepted" id="terms_accepted" value="1"'
					.	( $accepted ? ' checked="checked" disabled="disabled" ' : '' )
					.	'/> '
					.	'<label for="terms_accepted">'
					.	$txtTerms
					.	'</label></div>'
				;
				if ( ! $accepted ) {
					$settings			.=	'<span class="cb_button_wrapper">'
						.	'<button type="submit" id="cbTermsAccept" title="' . htmlspecialchars( CBPTXT::T( $basket_requiredtermserror ) ) . '">' . CBPTXT::Th("Accept Terms") . '</button>'
						.	'</span>'
					;
				}
				$getParams				=	$accepted ? '#' : $paymentBasket->getShowBasketUrl( false );
				$formHiddens			=	$accepted ? array( 'terms_accepted' => 1 ) : array();
				$result					.=	'<div class="cbregTerms">' . $subscriptionsGUI->drawForm( $settings, null, $formHiddens, $getParams ) . "</div>\n";
			} else {
				$accepted				=	false;
			}
		} else {
			$accepted					=	true;
		}

		$result							.=	'<div class="cbpayChoices cbclearboth"'
			.	( $termsCanBeDisplayed && $txtTerms && ! $accepted ? ' style="display:none;"' : '' )
			.	">\n "
			.	implode ( "\n  ", $payChoicesHtmlBottomArray )
			.	"\n</div>\n";
		if ( $txtFinal ) {
			$result						.=	'<div class="cbregFinalText">' . CBPTXT::Th( $txtFinal ) . "</div>\n";
		}

		$result							=	'<div class="cbpayBasketView">' . $result . '</div>';
		if ( ! $ajax ) {
			$result						=	'<div id="cbpayOrderContainer">'	// Needed for Javascript delegated binding
				.	$result
				.	'</div>';
		}
		return $result;
	}
 /**
  * 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;
 }
 /**
  * Called just before emailing each user from CB Users management backend
  *
  * @param  UserTable  $user
  * @param  string     $emailSubject
  * @param  string     $emailBody
  * @param  int        $mode
  * @param  array      $extraStrings    Entries can be filled in this function and will be used to email
  * @param  boolean    $simulationMode
  */
 public function onBeforeBackendUserEmail(&$user, &$emailSubject, &$emailBody, $mode, &$extraStrings, $simulationMode)
 {
     if (cbpaidApp::authoriseAction('cbsubs.usersubscriptionview')) {
         if ($this->filter_cbpaidplan > 0) {
             $params = cbpaidApp::settingsParams();
             $showtime = $params->get('showtime', '1') == '1';
             $plansMgr = cbpaidPlansMgr::getInstance();
             $plan = $plansMgr->loadPlan((int) $this->filter_cbpaidplan);
             $sub = $plan->loadLatestSomethingOfUser($user->id, $this->filter_cbpaidsubstate);
             $extraStrings['subscription_start_date'] = $sub ? cbFormatDate($sub->getSubscriptionDate(), 1, $showtime) : CBPTXT::T('No subscription');
             if ($plan->isProductWithExpiration()) {
                 if ($sub) {
                     $extraStrings['subscription_end_date'] = $sub->getFormattedExpirationDateText();
                 } else {
                     $extraStrings['subscription_end_date'] = CBPTXT::T('No subscription');
                 }
             }
             $extraStrings['subscription_lastrenew_date'] = $sub ? cbFormatDate($sub->getLastRenewDate(), 1, $showtime) : CBPTXT::T('No subscription');
         }
     }
 }
	/**
	 * 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 );
		}
	}
	/**
	 * Chainable: Get the viewer class for template, view and output
	 *
	 * @param  string                 $template  Template to load
	 * @param  string                 $view      View
	 * @param  string                 $output    Output
	 * @return cbpaidTemplateHandler
	 */
	public static function getViewer( $template, $view, $output = 'html' ) {
		$instance				=	new self();
		if ( ! $template ) {
			$template			=	cbpaidApp::settingsParams()->get( 'template', 'default' );
		}
		return $instance->_getViewer( $template, $view, $output );
	}
 /**
  * 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');
     }
 }
 /**
  * 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;
 }