/** * Creates a something of a plan * * @param cbpaidProduct $plan * @param UserTable $user * @param string $state * @param int $subscriptionTime */ protected function createSomething($plan, $user, $state, $subscriptionTime) { global $_CB_database; $replacesSubId = null; $reason = 'N'; if ($state == 'X' && $plan->get('item_type') != 'usersubscription') { // safeguard for donations and merchandises: they do not expire!, so set them as cencelled if import is as expired: $state = 'C'; } /* if ( $plan->get( 'exclusive' ) && ( $plan->get( 'item_type' ) == 'usersubscription' ) && ( $state == 'A' ) ) { $incompatible = false; $paidUserExtension = cbpaidUserExtension::getInstance( $user->id ); $subscriptions = $paidUserExtension->getUserSubscriptions( null, false ); foreach ( $subscriptions as $s ) { if ( ( $s->parent_plan == $plan->get( 'parent' ) ) && $s->checkIfValid() ) { $sPlan = $s->getPlan(); if ( $sPlan->get( 'exclusive' ) && ( $sPlan->get( 'item_type' ) == 'usersubscription' ) ) { // This other exclusive user subscription with same parent plan is active: then it is an upgrade from that subscription $replacesSubId = array( $s->plan_id, $s->id ); $reason = 'U'; break; } } } if ( $incompatible ) { continue; } } */ $parentSubId = null; if ($plan->get('parent')) { $plansMgr = cbpaidPlansMgr::getInstance(); $parentPlan = $plansMgr->loadPlan($plan->get('parent')); $parentSub = $parentPlan->loadLatestSomethingOfUser($user->id, null); if ($parentSub) { $parentSubId = array($parentSub->plan_id, $parentSub->id); } } $postdata = array(); $price = null; $recurringPrice = null; $subscription = $plan->createProductThing($user, $postdata, $reason, $state == 'A' ? 'I' : $state, $replacesSubId, null, $subscriptionTime, $price, $recurringPrice, $parentSubId); if ($state == 'A') { $subscription->activate($user, $subscriptionTime); } elseif ($state == 'X') { /** @var cbpaidUsersubscriptionRecord $subscription */ if (is_callable(array($subscription, 'computeExpiryTimeIfActivatedNow'))) { // Sets expiry_date for expired user subscriptions: $expiry = $subscription->computeExpiryTimeIfActivatedNow($subscriptionTime); $subscription->expiry_date = $expiry === null ? $_CB_database->getNullDate() : $_CB_database->getUtcDateTime($expiry); if (!$subscription->store()) { trigger_error('subscription store error:' . htmlspecialchars($_CB_database->getErrorMsg()), E_USER_ERROR); } } } }
/** * Checks for the user's subscriptions, * and if no subscription found (and free memberships not allowed): * redirects or returns FALSE depending on $redirect * Otherwise returns TRUE * * @param string $functionName Name of calling function (CB API functions: getDisplayTab, getEditTab, onDuringLogin, getTabComponent, module: mod_subscriptions ) * @param int $userId Check a specific user * @param boolean $redirect If should redirect in case of expiration * @return boolean if $redirect == false: TRUE: membership valid, FALSE: membership not valid, otherwise: TRUE or REDIRECT ! */ public function checkExpireMe($functionName, $userId = null, $redirect = true) { global $_CB_framework; static $notCalled = true; static $notMassExpired = true; if ($notCalled && $_CB_framework->GetUi() == 1) { if ($userId == null) { $params = cbpaidApp::settingsParams(); if ($notMassExpired && $params->get('massexpirymethod', 0) == 1) { // mass-expire 10 subscriptions at a time on the way if not exipring a particular user: $plansMgr = cbpaidPlansMgr::getInstance(); $plansMgr->checkAllSubscriptions(10); $notMassExpired = false; } $userId = $_CB_framework->myId(); } if ($userId) { // make sure to not check more than once: $notCalled = false; $null = null; $paidUserExtension = cbpaidUserExtension::getInstance($userId); $subscriptionOk = $paidUserExtension->checkUserSubscriptions(false, $null, 'X', true); if (!$subscriptionOk) { if ($redirect) { $this->_redirectExpiredMembership($userId); return false; // if we are already displaying the correct screen... } else { return false; } } } } return true; }
/** * 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; }
/** * View for <param type="private" class="cbpaidParamsExt" method="checkAllSubscriptions">... * * @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 checkAllSubscriptions($value, &$pluginParams, $name, &$param, $control_name, $control_name_name, $view, &$modelOfData, &$modelOfDataRows, &$modelOfDataRowsNumber) { $size = $param->attributes('size'); if ($size == '') { $size = 100; } $cbsubsParams = cbpaidApp::settingsParams(); if ($cbsubsParams->get('massexpirymethod') < 3) { $plansMgr = cbpaidPlansMgr::getInstance(); $total = $plansMgr->checkAllSubscriptions((int) $size); if ($total == $size) { $total .= ' (' . CBPTXT::T("reload page for more mass expiries") . ')'; } } else { $total = '0 (' . CBPTXT::T("no mass expiry from admin area, Settings-Global-Massexpiry is only by cron tasks") . ')'; } $basketsMgr = cbpaidOrdersMgr::getInstance(); $expBaskets = $basketsMgr->timeoutUnusedBaskets(null, (int) $size); return $total . ' / ' . $expBaskets; }
/** * 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'); } } }
/** * Used by XML for Backend: * * 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 cbpaidProduct */ public static function productObjects($resultsArray) { $plansMgr = cbpaidPlansMgr::getInstance(); $objectsArray = $plansMgr->getObjects($resultsArray); return $objectsArray; }
/** * loads the plan corresponding to this subscription into internal variable * * @return void */ protected function loadPlan( ) { $plansMgr =& cbpaidPlansMgr::getInstance(); $this->_plan =& $plansMgr->loadPlan( $this->plan_id ); }
/** * WARNING: UNCHECKED ACCESS! On purpose unchecked access for M2M operations * Generates the HTML to display for a specific component-like page for the tab. WARNING: unchecked access ! * @param TabTable|null $tab the tab database entry * @param UserTable $user the user being displayed * @param int $ui 1 for front-end, 2 for back-end * @param array $postdata _POST data for saving edited tab content as generated with getEditTab * @return mixed either string HTML for tab content, or false if ErrorMSG generated */ public function getTabComponent( /** @noinspection PhpUnusedParameterInspection */ $tab, $user, $ui, $postdata ) { global $_CB_database, $_CB_framework, $_POST; $return = ''; $paid = false; $oldignoreuserabort = ignore_user_abort(true); $allowHumanHtmlOutput = true; // this will be reverted in case of M2M server-to-server notifications $act = $this->base->_getReqParam( 'act' ); $actPosted = isset($_POST[$this->base->_getPagingParamName('act')]); if ( $act === null ) { $act = $this->base->input( 'act', null, GetterInterface::COMMAND ); $actPosted = $this->base->input( 'post/act', null, GetterInterface::COMMAND ) !== null; } $post_user_id = (int) cbGetParam( $_GET, 'user', 0 ); if ( $actPosted && ( $post_user_id > 0 ) ) { $access = false; $myId = $_CB_framework->myId(); if ( is_object( $user ) ) { if ( $myId == 0 ) { if ( in_array( $act, array( 'saveeditinvoiceaddress', 'saveeditbasketintegration', 'showbskt' ) ) ) { $access = true; } else { $paidsubsManager =& cbpaidSubscriptionsMgr::getInstance(); if ( ! $paidsubsManager->checkExpireMe( __FUNCTION__, $user->id, false ) ) { // expired subscriptions: we will allow limited access to: if ( in_array( $act, array( 'upgrade', 'pay', 'reactivate', 'resubscribe', 'display_subscriptions' ) ) ) { $access = true; } } } } else { if ( ( $ui == 1 && ( $user->id == $myId ) ) || ( cbpaidApp::authoriseAction( 'cbsubs.usersubscriptionmanage' ) ) ) { $access = true; } } } else { $return = CBPTXT::T("User does not exist") . '.'; } if ( ! $access ) { $return .= '<br />' . CBPTXT::T("Not authorized action") . '.'; return $return; } cbSpoofCheck( 'plugin' ); // anti-spoofing check // renew or upgrade subscription payment form: $params = $this->params; $now = $_CB_framework->now(); $subscriptionsGUI = new cbpaidControllerUI(); $subscriptionIds = $subscriptionsGUI->getEditPostedBoxes( 'id' ); if ( $subscriptionIds == array( 0 ) ) { $subscriptionIds = array(); } if ( $post_user_id && ( $user->id == $post_user_id ) ) { outputCbTemplate(); $this->base->outputRegTemplate(); outputCbJs(); switch ( $act ) { case 'upgrade': // upgrade an existing subscription // display basket and payment buttons or redirect for payment depending if multiple payment choices or intro text present: $chosenPlans = $subscriptionsGUI->getAndCheckChosenUpgradePlans( $postdata, $user, $now ); if ( ( ! is_array( $chosenPlans ) ) || ( count( $chosenPlans ) == 0 ) ) { $subTxt = CBPTXT::T( $params->get( 'subscription_name', 'subscription' ) ); $return .= ( is_string( $chosenPlans ) ? $chosenPlans . '<br />' : '' ) . sprintf( CBPTXT::Th("Please press back button and select the %s plan to which you would like to upgrade."), $subTxt ); break; } $introText = CBPTXT::Th( $params->get( 'intro_text_upgrade', null ) ); //TBD: check if already exists (reload protection): $paymentBasket = cbpaidControllerOrder::createSubscriptionsAndPayment( $user, $chosenPlans, $postdata, $subscriptionIds, null, 'R', CBPTXT::T("Upgrade"), 'U' ); if ( is_object( $paymentBasket ) ) { $return = cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, $introText ); } else { $return = $paymentBasket; // show messages as nothing to pay. } break; case 'pay': // pay for an unpaid subscription // display basket and payment buttons or redirect for payment depending if multiple payment choices or intro text present: $plan = $this->base->_getReqParam( 'plan' ); if ( ( ! $plan ) || ( ! isset( $subscriptionIds[$plan] ) ) || ( ! $subscriptionIds[$plan] ) ) { $subTxt = CBPTXT::T( $params->get( 'subscription_name', 'subscription' ) ); $return .= sprintf( CBPTXT::Th("Please press back button and select a %s plan."), $subTxt ); break; } $plansMgr =& cbpaidPlansMgr::getInstance(); $chosenPlans = array(); $chosenPlans[(int) $plan] = $plansMgr->loadPlan( (int) $plan ); $introText = CBPTXT::Th( $params->get( 'intro_text', null ) ); $paymentStatus = null; $return = cbpaidControllerOrder::showPaymentForm( $user, $chosenPlans, $introText, $subscriptionIds, $paymentStatus ); break; case 'renew': // renew a still valid subscription case 'reactivate': // reactivate an expired subscription case 'resubscribe': // resubscribe a cancelled subscription // display basket and payment buttons or redirect for payment depending if multiple payment choices or intro text present: $plan = $this->base->_getReqParam( 'plan' ); if ( ( ! $plan ) || ( ! isset( $subscriptionIds[$plan] ) ) || ( ! $subscriptionIds[$plan] ) ) { $subTxt = CBPTXT::T( $params->get( 'subscription_name', 'subscription' ) ); $return .= sprintf( CBPTXT::Th("Please press back button and select a %s plan."), $subTxt ); break; } $plansMgr =& cbpaidPlansMgr::getInstance(); $chosenPlans = array(); $chosenPlans[(int) $plan] = $plansMgr->loadPlan( (int) $plan ); $paidSomethingMgr =& cbpaidSomethingMgr::getInstance(); $subscription = $paidSomethingMgr->loadSomething( $subscriptionIds[$plan][0], $subscriptionIds[$plan][1] ); global $_PLUGINS; $_PLUGINS->loadPluginGroup( 'user', 'cbsubs.' ); $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin'); $_PLUGINS->trigger( 'onCPayAfterPlanRenewalSelected', array( &$chosenPlans[(int) $plan], &$subscription, $act ) ); if ( $_PLUGINS->is_errors() ) { $return .= $_PLUGINS->getErrorMSG(); break; } $introText = CBPTXT::Th( $params->get( 'intro_text_renew', null ) ); //TBD: check if already exists (reload protection): $paymentBasket = cbpaidControllerOrder::createSubscriptionsAndPayment( $user, $chosenPlans, $postdata, $subscriptionIds, null, null, CBPTXT::T("Renew"), 'R' ); if ( is_object( $paymentBasket ) ) { $return = cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, $introText ); } else { $return = $paymentBasket; // show messages as nothing to pay. } break; case 'unsubscribe': // request to unsubscribe an active subscription // display unsubscribe confirmation form: $plan = $this->base->_getReqParam( 'plan' ); if ( ( ! $plan ) || ( ! isset( $subscriptionIds[$plan] ) ) || ( ! $subscriptionIds[$plan] ) ) { $subTxt = CBPTXT::T( $params->get( 'subscription_name', 'subscription' ) ); $return .= sprintf( CBPTXT::Th("Please press back button and select a %s plan."), $subTxt ); break; } $introText = CBPTXT::Th( $params->get( 'unsubscribe_intro_text' , null ) ); $return = $subscriptionsGUI->showUnsubscribeForm( $user, $introText, (int) $plan, (int) $subscriptionIds[$plan][1] ); break; case 'confirm_unsubscribe': // confirm previous request to unsubscribe an active subscription // unsubscribe confirmed: $plan = $this->base->_getReqParam( 'plan' ); if ( ( ! $plan ) || ( ! isset( $subscriptionIds[$plan] ) ) || ( ! $subscriptionIds[$plan] ) ) { $subTxt = CBPTXT::T( $params->get( 'subscription_name', 'subscription' ) ); $return .= sprintf( CBPTXT::Th("Please press back button and select a %s plan."), $subTxt ); break; } if ( ( $plan ) && ( count( $subscriptionIds ) == 1 ) ) { $unsubscribeConfText = CBPTXT::Th( $params->get( 'unsubscribe_confirmation_text', null ) ); $return = cbpaidControllerOrder::doUnsubscribeConfirm( $user, $unsubscribeConfText, (int) $plan, (int) $subscriptionIds[$plan][1] ); } break; case 'display_subscriptions': // unsubscribe cancelled: display subscriptions: $return = $this->base->displayUserTab( $user ); break; case 'showinvoice': // shows a particular user invoice: if ( $params->get( 'show_invoices', 1 ) ) { $invoiceNo = $this->base->_getReqParam( 'invoice' ); $return = $this->showInvoice( $invoiceNo, $user ); } break; case 'saveeditinvoiceaddress': case 'editinvoiceaddress': // this is the case of reload of invoicing address $invoicingAddressQuery = $params->get( 'invoicing_address_query' ); if ( $invoicingAddressQuery > 0 ) { $basketId = $this->base->_getReqParam( 'basket', 0 ); $hashToCheck = $this->base->_getReqParam( 'bck' ); $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); if ( $basketId && $paymentBasket->load( (int) $basketId ) && ( $paymentBasket->payment_status == 'NotInitiated' ) && ( $hashToCheck == $paymentBasket->checkHashUser( $hashToCheck ) ) ) { if ( ( $act == 'saveeditinvoiceaddress' ) && $this->base->input( 'actbutton', null, GetterInterface::COMMAND ) ) { // IE7-8 will return text instead of value and IE6 will return button all the time http://www.dev-archive.net/articles/forms/multiple-submit-buttons.html $return = $paymentBasket->saveInvoicingAddressForm( $user ); if ( $return === null ) { $paymentBasket->storeInvoicingDefaultAddress(); $introText = CBPTXT::Th( $params->get( 'intro_text', null ) ); $return .= cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, $introText ); } } else { // invoice has reloaded itself (e.g. for country change): $return = $paymentBasket->renderInvoicingAddressForm( $user ); } } else { $this->base->_setErrorMSG( CBPTXT::T("No unpaid payment basket found.") ); } } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } break; case 'saverecordpayment': case 'editrecordpayment': // this is the case of reload of the form $basketId = $this->base->_getReqParam( 'basket', 0 ); $hashToCheck = $this->base->_getReqParam( 'bck' ); $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); if ( $basketId && $paymentBasket->load( (int) $basketId ) && ( $paymentBasket->payment_status != 'Completed' ) && ( $hashToCheck == $paymentBasket->checkHashUser( $hashToCheck ) ) ) { if ( $paymentBasket->authoriseAction( 'cbsubs.recordpayments' ) ) { if ( ( $act == 'saverecordpayment' ) && $this->base->input( 'actbutton', null, GetterInterface::COMMAND ) ) { // IE7-8 will return text instead of value and IE6 will return button all the time http://www.dev-archive.net/articles/forms/multiple-submit-buttons.html $return = cbpaidRecordBasketPayment::saveRecordPayment( $paymentBasket->id ); if ( $return === null ) { $return .= CBPTXT::T("Payment recorded.") . ' <a href="' . $_CB_framework->userProfileUrl( $paymentBasket->user_id, true ) . '">' . CBPTXT::Th("View user profile") . '</a>'; } } else { // invoice has reloaded itself (e.g. for country change): $return = cbpaidRecordBasketPayment::displayRecordPaymentForm( $paymentBasket->id ); } } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } } else { $this->base->_setErrorMSG( CBPTXT::T("No unpaid payment basket found.") ); } break; default: cbNotAuth(); return ''; break; } } } elseif ( $this->base->_getReqParam( 'account' ) && ( ( (int) cbGetParam( $_GET, 'user', 0 ) ) > 0 ) ) { $account = $this->base->_getReqParam( 'account' ); $post_user_id = (int) cbGetParam( $_GET, 'user', 0 ); $user = CBuser::getUserDataInstance( (int) $post_user_id ); if ( $user->id ) { if ( isset( $_SESSION['cbsubs']['expireduser'] ) && ( $_SESSION['cbsubs']['expireduser'] == $user->id ) ) { // expired subscriptions of membership: show possibilities: $subscriptionsGUI = new cbpaidControllerUI(); outputCbTemplate(); $this->base->outputRegTemplate(); outputCbJs(); switch ( $account ) { case 'expired': $paidsubsManager =& cbpaidSubscriptionsMgr::getInstance(); if ( ! $paidsubsManager->checkExpireMe( __FUNCTION__, $user->id, false ) ) { // no valid membership: $return = $subscriptionsGUI->getShowSubscriptionUpgrades( $user, true ); } break; default: break; } } else { $return = CBPTXT::Th("Browser cookies must be enabled."); } } } elseif ( in_array( $act, array( 'setbsktpmtmeth', 'setbsktcurrency' ) ) ) { cbSpoofCheck( 'plugin' ); // anti-spoofing check $params = $this->params; outputCbTemplate(); $this->base->outputRegTemplate(); outputCbJs(); $basketId = $this->base->_getReqParam( 'bskt', 0 ); $hashToCheck = $this->base->_getReqParam( 'bck' ); $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); if ( $basketId && $paymentBasket->load( (int) $basketId ) && ( $paymentBasket->payment_status == 'NotInitiated' ) && ( $hashToCheck == $paymentBasket->checkHashUser( $hashToCheck ) ) ) { switch ( $act ) { case 'setbsktpmtmeth': if ( $params->get( 'payment_method_selection_type' ) == 'radios' ) { $chosenPaymentMethod = cbGetParam( $_POST, 'payment_method' ); $introText = CBPTXT::Th( $params->get( 'intro_text', null ) ); $return = $paymentBasket->saveBasketPaymentMethodForm( $user, $introText, $chosenPaymentMethod ); if ( $return === null ) { $return .= cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, $introText ); } } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } break; case 'setbsktcurrency': if ( $params->get( 'allow_select_currency', '0' ) ) { $newCurrency = cbGetParam( $_POST, 'currency' ); if ( $newCurrency ) { if ( in_array( $newCurrency, cbpaidControllerPaychoices::getInstance()->getAllCurrencies() ) ) { $paymentBasket->changeCurrency( $newCurrency ); } else { $this->base->_setErrorMSG( CBPTXT::T("This currency is not allowed") ); } $introText = CBPTXT::Th( $params->get( 'intro_text', null ) ); $return .= cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, $introText ); } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } } else { $this->base->_setErrorMSG( CBPTXT::T("Changes of currency of orders are not authorized") ); } break; default: cbNotAuth(); return ''; break; } } else { $this->base->_setErrorMSG( CBPTXT::T("No unpaid payment basket found.") ); } } elseif ( $act == 'cbsubsclass' ) { $pluginName = $this->base->_getReqParam( 'class' ); if ( preg_match( '/^[a-z]+$/', $pluginName ) ) { $element = 'cbsubs.' . $pluginName; global $_PLUGINS; $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin', $element ); $loadedPlugins =& $_PLUGINS->getLoadedPluginGroup( 'user/plug_cbpaidsubscriptions/plugin' ); $params = $this->params; foreach ($loadedPlugins as $p ) { if ( $p->element == $element ) { $pluginId = $p->id; $args = array( &$user, &$params, &$postdata ); /** @noinspection PhpUndefinedCallbackInspection */ $return = $_PLUGINS->call( $pluginId, 'executeTask', 'getcbsubs' . $pluginName . 'Tab', $args, null ); break; } } } } elseif ( $act && ( ! in_array( $act, array( 'showbskt', 'setbsktpmtmeth' ) ) ) && ( ( (int) cbGetParam( $_GET, 'user', 0 ) ) > 0 ) ) { if ( ! is_object( $user ) ) { return CBPTXT::T("User does not exist."); } $params = $this->params; $post_user_id = (int) cbGetParam( $_GET, 'user', 0 ); if ( $post_user_id && ( ( $user->id == $post_user_id ) || ( cbpaidApp::authoriseAction( 'cbsubs.usersubscriptionmanage' ) ) ) ) { outputCbTemplate(); $this->base->outputRegTemplate(); outputCbJs(); switch ( $act ) { case 'showinvoice': if ( $params->get( 'show_invoices', 1 ) ) { $invoiceNo = $this->base->_getReqParam( 'invoice', 0 ); // This also checks for cbpaidApp::authoriseAction on cbsubs.sales or cbsubs.financial access permissions: $return = $this->showInvoice( $invoiceNo, $user ); } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } break; case 'showinvoiceslist': $showInvoices = $params->get( 'show_invoices', 1 ); $invoicesShowPeriod = $params->get( 'invoices_show_period', '0000-06-00 00:00:00' ); $itsmyself = ( $_CB_framework->myId() == $user->id ); if ( $showInvoices && ( $itsmyself || ( cbpaidApp::authoriseAction( 'cbsubs.sales' ) || cbpaidApp::authoriseAction( 'cbsubs.financial' ) ) ) ) { $subscriptionsGUI = new cbpaidControllerUI(); $invoices = $this->_getInvoices( $user, $invoicesShowPeriod, false ); if ( $invoicesShowPeriod && ( $invoicesShowPeriod != '0000-00-00 00:00:00' ) ) { $cbpaidTimes =& cbpaidTimes::getInstance(); $periodText = $cbpaidTimes->renderPeriod( $invoicesShowPeriod, 1, false ); } else { $periodText = ''; } $return .= $subscriptionsGUI->showInvoicesList( $invoices, $user, $itsmyself, $periodText ); } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } break; case 'editinvoiceaddress': // this is the case of the initial edit address link if ( $params->get( 'invoicing_address_query' ) > 0 ) { $basketId = $this->base->_getReqParam( 'basket', 0 ); $hashToCheck = $this->base->_getReqParam( 'bck' ); $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); if ( $basketId && $paymentBasket->load( (int) $basketId ) && ( $paymentBasket->payment_status == 'NotInitiated' ) && ( $hashToCheck == $paymentBasket->checkHashUser( $hashToCheck ) ) ) { $return = $paymentBasket->renderInvoicingAddressForm( $user ); } else { $this->base->_setErrorMSG( CBPTXT::T("No unpaid payment basket found.") ); } } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } break; case 'showrecordpayment': $paymentBasketId = $this->base->_getReqParam( 'recordpayment', 0 ); if ( $paymentBasketId ) { $paymentBasket = new cbpaidPaymentBasket(); if ( $paymentBasket->load( (int) $paymentBasketId ) && $paymentBasket->authoriseAction( 'cbsubs.recordpayments' ) ) { // Auto-loads class: and authorization is checked inside: $return = cbpaidRecordBasketPayment::displayRecordPaymentForm( $paymentBasketId ); } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } break; default: $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); break; } } } elseif ( $act == 'showbskt' && ( ( ( (int) cbGetParam( $_GET, 'user', 0 ) ) > 0 ) ) || ( $this->base->_getReqParam( 'bskt', 0 ) && $this->base->_getReqParam( 'bck' ) ) ) { $basketId = $this->base->_getReqParam( 'bskt', 0 ); $hashToCheck = $this->base->_getReqParam( 'bck' ); // Basket integrations saving/editing url: if ( in_array($act, array( 'saveeditbasketintegration', 'editbasketintegration' ) ) ) { // edit is the case of edit or reload of integration form $integration = $this->base->_getReqParam( 'integration' ); $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); if ( preg_match( '/^[a-z]+$/', $integration ) && $basketId && $paymentBasket->load( (int) $basketId ) && ( $paymentBasket->payment_status == 'NotInitiated' ) && ( $hashToCheck == $paymentBasket->checkHashUser( $hashToCheck ) ) ) { global $_PLUGINS; $element = 'cbsubs.' . $integration; $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin', $element ); $results = $_PLUGINS->trigger( 'onCPayEditBasketIntegration', array( $integration, $act, &$paymentBasket ) ); $return = null; foreach ( $results as $r ) { if ( $r ) { $return .= $r; } } if ( $act == 'editbasketintegration' ) { if ( $return !== null ) { return $return; } } } else { $this->base->_setErrorMSG( CBPTXT::T("No unpaid payment basket found.") ); } } $post_user_id = (int) cbGetParam( $_GET, 'user', 0 ); if ( $post_user_id && ! ( ( is_object( $user ) && ( $user->id == $post_user_id ) ) ) ) { return CBPTXT::T("User does not exist."); } outputCbTemplate(); $this->base->outputRegTemplate(); outputCbJs(); $params = $this->params; $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); if ( $basketId && $paymentBasket->load( (int) $basketId ) && ( $paymentBasket->payment_status == 'NotInitiated' ) ) { if ( ! $post_user_id ) { $cbUser =& CBuser::getInstance( (int) $paymentBasket->user_id ); $user =& $cbUser->getUserData(); if ( ( ! is_object( $user ) ) || ! $user->id ) { return CBPTXT::T("User does not exist."); } } if ( ( $hashToCheck && $hashToCheck == $paymentBasket->checkHashUser( $hashToCheck ) ) || ( ( ! $hashToCheck ) && $paymentBasket->user_id && ( $paymentBasket->user_id == $_CB_framework->myId() ) ) ) { $introText = CBPTXT::Th( $params->get( 'intro_text', null ) ); $return .= cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, $introText ); } else { $this->base->_setErrorMSG( CBPTXT::T("Not authorized action") ); } } else { $this->base->_setErrorMSG( CBPTXT::T("No unpaid payment basket found.") ); } // } elseif ( isset($_REQUEST['result']) && isset( $_REQUEST['user'] ) && ( $_REQUEST['user'] > 0 ) ) { } elseif ( isset($_REQUEST['result']) && ( $this->base->_getReqParam('method') || $this->base->_getReqParam('gacctno') ) ) { // don't check license here so initiated payments can complete ! $params = $this->params; $method = $this->base->_getReqParam('method'); if ( ( $method == 'freetrial' ) || ( $method == 'cancelpay' ) ) { cbpaidApp::import( 'processors.freetrial.freetrial' ); cbpaidApp::import( 'processors.cancelpay.cancelpay' ); $className = 'cbpaidGatewayAccount' . $method; $payAccount = new $className( $_CB_database ); } else { $gateAccount = $this->base->_getReqParam('gacctno'); $payAccount = cbpaidControllerPaychoices::getInstance()->getPayAccount( $gateAccount ); if ( ! $payAccount ) { return ''; } } $payClass = $payAccount->getPayMean(); $paymentBasket = new cbpaidPaymentBasket($_CB_database); if ( $payClass && ( ( $this->base->_getReqParam('method') == $payClass->getPayName() ) || ( $this->base->_getReqParam('method') == null ) ) && $payClass->hashPdtBackCheck( $this->base->_getReqParam('pdtback') ) ) { // output for resultNotification: $return and $allowHumanHtmlOutput $return = $payClass->resultNotification( $paymentBasket, $postdata, $allowHumanHtmlOutput ); } if ( ! $paymentBasket->id ) { $this->base->_setErrorMSG(CBPTXT::T("No suitable basket found.")); } else { $user =& CBuser::getUserDataInstance( (int) $paymentBasket->user_id ); if ( $paymentBasket->payment_status == 'RegistrationCancelled' ) { // registration cancelled: delete payment basket and delete user after checking that he is not yet active: if ( $paymentBasket->load( (int) $paymentBasket->id ) ) { if ( $payClass->hashPdtBackCheck( $this->base->_getReqParam('pdtback') ) && ( ( $paymentBasket->payment_status == 'NotInitiated' ) || ( ( $paymentBasket->payment_status === 'Pending' ) && ( $paymentBasket->payment_method === 'offline' ) ) ) ) { $notification = new cbpaidPaymentNotification(); $notification->initNotification( $payClass, 0, 'P', $paymentBasket->payment_status, $paymentBasket->payment_type, null, $_CB_framework->now(), $paymentBasket->charset ); $payClass->updatePaymentStatus( $paymentBasket, 'web_accept', 'RegistrationCancelled', $notification, 0, 0, 0, true ); // This is a notification or a return to site after payment, we want to log any error happening in third-party stuff in case: cbpaidErrorHandler::keepTurnedOn(); } } } if ( $allowHumanHtmlOutput ) { // If frontend, we display result, otherwise, If Server-to-server notification: do not display any additional text here ! switch ( $paymentBasket->payment_status ) { case 'Completed': // PayPal recommends including the following information with the confirmation: // - Item name // - Amount paid // - Payer email // - Shipping address $newMsg = sprintf( CBPTXT::Th("Thank you for your payment of %s for the %s %s."), $paymentBasket->renderPrice(), $paymentBasket->item_name, htmlspecialchars( $payClass->getTxtUsingAccount( $paymentBasket ) ) ) // ' using your paypal account ' . $paymentBasket->payer_email . ' ' . $payClass->getTxtNextStep( $paymentBasket ); // . "Your transaction has been completed, and a receipt for your purchase has been emailed to you by PayPal. " // . "You may log into your account at www.paypal.com to view details of this transaction.</p>\n"; if ( $params->get( 'show_invoices' ) ) { $itsmyself = ( $_CB_framework->myId() == $user->id ); $subscriptionsGUI = new cbpaidControllerUI(); $newMsg .= '<p id="cbregviewinvoicelink">' . $subscriptionsGUI->getInvoiceShowAhtml( $paymentBasket, $user, $itsmyself, CBPTXT::Th("View printable invoice") ) . '</p>' ; } $paid = true; break; case 'Pending': $newMsg = sprintf( CBPTXT::Th("Thank you for initiating the payment of %s for the %s %s."), $paymentBasket->renderPrice(), $paymentBasket->item_name, htmlspecialchars( $payClass->getTxtUsingAccount( $paymentBasket ) ) ) // ' using your paypal account ' . $paymentBasket->payer_email . ' ' . $payClass->getTxtNextStep( $paymentBasket ); // . "Your payment is currently being processed. " // . "A receipt for your purchase will be emailed to you by PayPal once processing is complete. " // . "You may log into your account at www.paypal.com to view status details of this transaction.</p>\n"; break; case 'RegistrationCancelled': $newMsg = $payClass->getTxtNextStep( $paymentBasket ); break; case 'FreeTrial': $newMsg = CBPTXT::Th("Thank you for subscribing to") . ' ' . $paymentBasket->item_name . '.' . ' ' . $payClass->getTxtNextStep( $paymentBasket ); break; case null: $newMsg = CBPTXT::T("Payment basket does not exist."); break; case 'NotInitiated': $newMsg = ''; break; case 'RedisplayOriginalBasket': if ( $paymentBasket->load( (int) $paymentBasket->id ) && ( $paymentBasket->payment_status == 'NotInitiated' ) ) { $introText = CBPTXT::Th( $params->get( 'intro_text', null ) ); $return .= cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, $introText ); } $newMsg = ''; break; case 'Processed': case 'Denied': case 'Reversed': case 'Refunded': case 'Partially-Refunded': default: $newMsg = $payClass->getTxtNextStep( $paymentBasket ); // "<p>Your transaction is not cleared and has currently following status: <strong>" . $paymentBasket->payment_status . ".</strong></p>" // . "<p>You may log into your account at www.paypal.com to view status details of this transaction.</p>"; break; } if ( in_array( $paymentBasket->payment_status, array( 'Completed', 'Pending' ) ) ) { $subscriptions = $paymentBasket->getSubscriptions(); $texts = array(); // avoid repeating several times identical texts: if ( is_array( $subscriptions ) ) { foreach ( $subscriptions as $sub ) { /** @var $sub cbpaidSomething */ $thankYouParam = ( $paymentBasket->payment_status == 'Completed') ? 'thankyoutextcompleted' : 'thankyoutextpending'; $thankYouText = $sub->getPersonalized( $thankYouParam, true ); if ( $thankYouText && ! in_array( $thankYouText, $texts ) ) { $texts[] = $thankYouText; if ( strpos( $thankYouText, '<' ) === false ) { $msgTag = 'p'; } else { $msgTag = 'div'; } $newMsg .= '<' . $msgTag . ' class="cbregThanks" id="cbregThanks' . $sub->plan_id . '">' . $thankYouText . '</' . $msgTag . ">\n"; } } } } if ( $newMsg ) { $return .= '<div>' . $newMsg . '</div>'; } if ( $paid && ( $_CB_framework->myId() < 1 ) && ( cbGetParam( $_REQUEST, 'user', 0 ) == $paymentBasket->user_id ) ) { $_CB_database->setQuery( "SELECT * FROM #__comprofiler c, #__users u WHERE c.id=u.id AND c.id=".(int) $paymentBasket->user_id ); if ( $_CB_database->loadObject( $user ) && ( $user->lastvisitDate == '0000-00-00 00:00:00' ) ) { $return = '<p>' . implode( '', getActivationMessage( $user, 'UserRegistration' ) ) . '</p>' . $return; } } } } } else { cbNotAuth(); return ' ' . CBPTXT::T("No result."); } if ( $allowHumanHtmlOutput ) { $allErrorMsgs = $this->base->getErrorMSG( '</div><div class="error">' ); if ( $allErrorMsgs ) { $errorMsg = '<div class="error">' . $allErrorMsgs . '</div>'; } else { $errorMsg = null; } /** @var string $return */ if ( ( $return == '' ) && ( $errorMsg ) ) { $this->base->outputRegTemplate(); $return = $errorMsg . '<br /><br />' . $return; $return .= cbpaidControllerOrder::showBasketForPayment( $user, $paymentBasket, '' ); } else { $return = $errorMsg . $return; } } if ( ! is_null( $oldignoreuserabort ) ) { ignore_user_abort($oldignoreuserabort); } return $return; }
/** * WARNING: UNCHECKED ACCESS! On purpose unchecked access for M2M operations * Generates the HTML to display for a specific component-like page for the tab. WARNING: unchecked access ! * @param null $tab * @param UserTable $user the user being displayed * @param int $ui 1 for front-end, 2 for back-end * @param array $postdata _POST data for saving edited tab content as generated with getEditTab * @return mixed either string HTML for tab content, or false if ErrorMSG generated */ public function getCBpluginComponent($tab, &$user, $ui, &$postdata) { global $_CB_framework, $ueConfig, $_GET; cbpaidErrorHandler::on(); $result = null; $do = cbGetParam($_GET, 'do'); switch ($do) { case null: $return = $this->getTabComponent($tab, $user, $ui, $postdata); cbpaidErrorHandler::keepTurnedOn(); break; case 'display_subscriptions': if ($user && $user->id && $_CB_framework->myId()) { $regTitle = strip_tags(CBPTXT::T($this->params->get('regTitle', "Subscriptions"))); outputCbTemplate(); $_CB_framework->setPageTitle($regTitle); $_CB_framework->appendPathWay($regTitle); $pre = '<div class="cbPageOuter"><div class="cbPageInner">'; $post = '</div></div><div class="cbClr"> </div>'; $return = $pre . $this->displayUserTab($user) . $post; } else { if ($_CB_framework->getCfg('allowUserRegistration') == '0' && (!isset($ueConfig['reg_admin_allowcbregistration']) || $ueConfig['reg_admin_allowcbregistration'] != '1')) { $return = _UE_NOT_AUTHORIZED . '<br />' . _UE_DO_LOGIN; } else { /* $registrationUrl = cbSef( 'index.php?option=com_comprofiler&task=registers' ); $registrationLink = '<a href="' . $registrationUrl . '">' . _UE_REGISTER . '</a>'; $loginRegisterText = sprintf( CBPTXT::Th("Please login or %s"), $registrationLink ); $return = _UE_NOT_AUTHORIZED . '<br /><br />' . $loginRegisterText; */ $accessPlans = null; $return = cbpaidControllerOffer::displaySpecificPlans($accessPlans, null, $user, ''); } } break; case 'accessdenied': $params = cbpaidApp::settingsParams(); $accessRedirectLink = $params->get('subscriptionNeededRedirectLink'); if ($accessRedirectLink) { $textMessage = $params->get('subscriptionNeededText', "A membership is needed for access."); $return = null; cbRedirect(cbSef($accessRedirectLink, false), CBPTXT::T($textMessage), 'warning'); } else { /** @noinspection PhpIncludeInspection */ include_once cbpaidApp::getAbsoluteFilePath('plugin/cbsubscontent/cbsubs.content_deniedview.php'); $accessDeniedView = new cbpaidContentAccessDeniedView(); $return = $accessDeniedView->display($user, $this); } break; case 'displayplans': $plansParam = cbGetParam($_GET, 'plans'); $plans = null; $preselect = null; if ($plansParam) { $plansParam = explode('-', $plansParam); foreach ($plansParam as $p) { $pN = (int) $p; if ($pN) { $plans[] = $pN; if (substr($p, -1) == 's') { $preselect[] = $pN; } } } } if ($user === null || $user->id == $_CB_framework->myId()) { $introText = CBPTXT::Th($this->params->get('plansDisplayIntroText', "We suggest subscribing to following subscriptions:")); $return = cbpaidControllerOffer::displaySpecificPlans($plans, $preselect, $user, $introText); } else { $return = _UE_NOT_AUTHORIZED; } break; case 'massexpire': // cron $params = cbpaidApp::settingsParams(); $key = cbGetParam($_GET, 'key'); if ($key && $key == md5($params->get('license_number')) && $params->get('massexpirymethod', 0) >= 2) { $limit = $params->get('massexpirynumber', 100); // mass-expire 100 subscriptions at a time on the way if not exipring a particular user: $plansMgr = cbpaidPlansMgr::getInstance(); $plansMgr->checkAllSubscriptions((int) $limit); $return = null; } else { $return = CBPTXT::Th("Invalid mass-expiry link: link is in global CBSubs settings."); } break; case 'autopayments': // cron $params = cbpaidApp::settingsParams(); $key = cbGetParam($_GET, 'key'); if ($key && $key == md5($params->get('license_number'))) { $limit = $params->get('massautorenewalsnumber', 100); // mass-autorenew 100 subscriptions at a time: $results = cbpaidOrdersMgr::getInstance()->triggerScheduledAutoRecurringPayments((int) $limit); $return = implode("\r\n\r\n", $results); $massrenewalemail = trim($params->get('massrenewalemail', '')); if ($massrenewalemail) { cbimport('cb.notification'); $recipients = explode(',', $massrenewalemail); if ($return) { $body = CBPTXT::T("CBSubs has just processed auto-recurring payments as follows:") . "\r\n\r\n" . $return . "\r\n\r\n" . CBPTXT::T("This is an automated email, do not reply.") . "\r\n\r\n"; comprofilerMail('', '', $recipients, CBPTXT::T("CBSubs has processed auto-recurring payments"), $body); } } if ($params->get('massrenewaloutputincron', 1) != 1) { // silence output to Cron: $return = null; } } else { $return = CBPTXT::Th("Invalid auto-renewals link: link is in global CBSubs settings."); } break; default: $return = sprintf(CBPTXT::Th("No valid %s action chosen"), '"do"') . '.'; break; } cbpaidErrorHandler::off(); return $return; }
/** * Gets all plans GIDs * * @param UserTable $user User to check for * @return array ( $block, $gid ) */ protected function _allPlansGid($user) { global $_CB_framework; // Determine highest new $gid (0 means nothing left): $registeredGid = (int) $_CB_framework->acl->mapGroupNamesToValues('Registered'); $allGids = array($registeredGid => $registeredGid); $plansMgr = cbpaidPlansMgr::getInstance(); $plans = $plansMgr->loadPublishedPlans($user, true, 'any', null); foreach ($plans as $p) { $planGid = (int) $p->get('usergroup'); if ($planGid) { $allGids[$planGid] = $planGid; } } return $allGids; }
/** * Loads all of Something of user $user. * * @param UserTable $user The user * @param string $status Optionally the status of the something ('A'=active, 'X'=expired, and so on) * @return cbpaidSomething[][] */ public static function getAllSomethingOfUser($user, $status = 'A') { static $somethings = array(); $statusIndex = $status ? $status : 'ZZ'; if (!isset($somethings[$user->id][$statusIndex])) { $somethings[$user->id][$statusIndex] = array(); $plansMgr = cbpaidPlansMgr::getInstance(); $plans = $plansMgr->loadPublishedPlans($user, true, 'any', null); foreach ($plans as $plan) { // $plan = NEW cbpaidProduct(); if (!isset($somethings[$user->id][$statusIndex][$plan->item_type])) { $somethings[$user->id][$statusIndex][$plan->item_type] = $plan->newSubscription()->loadTheseSomethingsOfUser($user->id, $status); } } } return $somethings[$user->id][$statusIndex]; }
/** * @return array */ public function plans() { $plansList = array(); if ( $this->installed() ) { $plansMgr = cbpaidPlansMgr::getInstance(); $plans = $plansMgr->loadPublishedPlans( null, true, 'any', null ); if ( $plans ) { $plansList = array(); foreach ( $plans as $k => $plan ) { $plansList[] = moscomprofilerHTML::makeOption( (string) $k, $plan->get( 'alias' ) ); } } } return $plansList; }
/** * Creates a new (or loads an existing) subscription, and if it's non-free: * Creates a payment basket if there is not already one * ---- and then displays payment processing mask, button, or redirects * If it's free: activates account and does not return anything. * * @param UserTable $user * @param cbpaidProduct[] $chosenPlans array of cbpaidProduct : Chosen plans to pay * @param array $postdata $_POST array for the parameters of the subscription plans * @param array|null $replacesSubscriptionIds In fact: the existing one in all cases, except if new to be created. * @param array|null $existingSubscriptionIds In fact: the new one in case of upgrade ! * @param string $status subscription status: 'R'=registered (default) , 'I'=illegal, 'A'=active, etc. * @param string $prefixText text to prefix the payment items (default: null) * @param string $reason payment reason: 'N'=new subscription (default), 'R'=renewal, 'U'=update * @param string $payment 'now' (default), 'free' * @return cbpaidPaymentBasket|string object if something to pay, otherwise HTML text for message. */ public static function createSubscriptionsAndPayment( &$user, $chosenPlans, $postdata, $replacesSubscriptionIds = null, $existingSubscriptionIds = null, $status = 'R', $prefixText = null, $reason='N', $payment = 'now' ) { global $_CB_framework, $_CB_database; $subscriptionTime = $_CB_framework->now(); /** @var cbpaidSomething[] $subscriptions */ $subscriptions = array(); $needToPay = false; //TBD LATER: Handle fully payment baskets as baskets, adding/replacing the content with the new items: $paymentBasket =& cbpaidPaymentBasket::getInstanceBasketOfUser( $user->id, false ); //TBD could be true to avoid old baskets ? if ( $paymentBasket->id ) { // otherwise show existing basket: return $paymentBasket; } if ( ! ( $chosenPlans && ( count( $chosenPlans ) > 0 ) ) ) { trigger_error( 'createSubscriptionsAndPayment:: called without plans chosen !', E_USER_ERROR ); } // 1. add subscription records if not existing: pass 1: parents, pass 2: children: $pass = 0; while ( ++$pass <= 2 ) { foreach ( $chosenPlans as $plan ) { $parentPlan = $plan->get( 'parent' ); if ( ( ( $pass == 1 ) && ( $parentPlan == 0 ) ) || ( ( $pass == 2 ) && ( $parentPlan != 0 ) ) ) { $planId = $plan->get( 'id' ); /* $reasonInCaseExpired = $reason; */ // find replaced subscription id: $replacesSubId = null; if ( $replacesSubscriptionIds && isset( $replacesSubscriptionIds[$planId] ) ) { $replacesSubId = $replacesSubscriptionIds[$planId]; /* //TBD later: need to check if we really want to renew an existing subscription when there is an interruption. if ( $reason == 'R' ) { $paidSomethinMgr =& cbpaidSomethingMgr::getInstance(); $replacesSub =& $paidSomethinMgr->loadSomething( $replacesSubId[0], $replacesSubId[1] ); if ( $replacesSub ) { if ( ! $replacesSub->checkIfValid( $subscriptionTime ) ) { } } } */ } else { if ( $reason == 'R' ) { trigger_error( 'createSubscriptionsAndPayment::no existing subscription for renewal !', E_USER_ERROR ); exit; } } // find existing plan+subscription id: $existingSubId = null; if ( $reason != 'R' ) { // new or upgrade: create or load $subscription: if ( $existingSubscriptionIds && isset( $existingSubscriptionIds[$planId] ) ) { $existingSubId = $existingSubscriptionIds[$planId]; } } // check that subscription is renewable if getting renewed: if ( ( $reason == 'R' ) && $replacesSubId ) { $paidSomethingMgr =& cbpaidSomethingMgr::getInstance(); $subscription = $paidSomethingMgr->loadSomething( $replacesSubId[0], $replacesSubId[1] ); if ( ! $subscription->checkIfRenewable() ) { trigger_error( sprintf( 'createSubscriptionsAndPayment::Renewal not allowed !' ), E_USER_WARNING ); return 'Unexpected condition: Renewal not allowed !'; } } // find parent subscription id if exists: $parentSubId = null; if ( $parentPlan ) { switch ( $reason ) { case 'R': // renew: don't change anything in the existing subscription (no update on NULL): // $parentSubId = null; break; case 'U': // upgrade: check if parent subscription is upgraded same time: if ( isset( $subscriptions[$parentPlan] ) ) { $parentSubId = array( (int) $subscriptions[$parentPlan]->plan_id, (int) $subscriptions[$parentPlan]->id ); } else { // if not: try to find the existing subscription in database: if ( $existingSubId ) { $paidSomethinMgr =& cbpaidSomethingMgr::getInstance(); $thisSub = $paidSomethinMgr->loadSomething( $existingSubId[0], $existingSubId[1] ); if ( $thisSub ) { // then try to find parent subscription of the existing subscription: if ( $thisSub->parent_plan && $thisSub->parent_subscription ) { $thisSubParent = $paidSomethinMgr->loadSomething( $thisSub->parent_plan, $thisSub->parent_subscription ); if ( $thisSubParent ) { $parentSubId = array( $thisSubParent->parent_plan, $thisSubParent->parent_subscription ); } } } else { trigger_error( sprintf( 'createSubscriptionsAndPayment::no existing subscription id %d found in database for upgraded plan id %d !', $existingSubId[1], $existingSubId[0] ), E_USER_WARNING ); } } else { // try finding subscription of parent plan by this user: $plansMgr =& cbpaidPlansMgr::getInstance(); $parPlan = $plansMgr->loadPlan( $parentPlan ); if ( $parPlan ) { $something = $parPlan->newSubscription(); $foundParent = $something->loadLatestSomethingOfUser( $user->id ); if ( $foundParent ) { $parentSubId = array( $something->plan_id, $something->id ); } } } } break; case 'N': default: // new: find parent subscription: if ( isset( $subscriptions[$parentPlan] ) ) { $parentSubId = array( (int) $subscriptions[$parentPlan]->plan_id, (int) $subscriptions[$parentPlan]->id ); } else { trigger_error( sprintf( 'createSubscriptionsAndPayment::no existing subscription for parent plan id %d of plan %d in new subscription !', $parentPlan, $planId ), E_USER_WARNING ); } break; } } // creates the subscription of the correct type: $price = false; // returned values from next line: $recurringPrice = false; // returned values from next line: $subscriptions[$planId] = $plan->createProductThing( $user, $postdata, $reason, $status, $replacesSubId, $existingSubId, $subscriptionTime, $price, $recurringPrice, $parentSubId ); if ( ( $price === false ) && ( $recurringPrice === false ) ) { unset( $subscriptions[$planId] ); // can't be subscribed/purchased unset( $chosenPlans[$planId] ); } elseif ( ( $price > 0 ) || ( $recurringPrice > 0 ) ) { // $lastSubscriptionId = $subscriptions[$planId]->id; // $lastPlanId = $planId; $needToPay = true; } } } } // Sort subscriptions, so they are presented in basket in same order as on the plans selection: $sortedSubscriptions = array(); foreach ( array_keys( $chosenPlans ) as $id ) { $sortedSubscriptions[$id] = $subscriptions[$id]; } if ( ( $payment == 'free' ) || ( ! $needToPay ) ) { //TBD: Should we activate already what can be activated (check for hierarchy) !??? // Free plan: no payment ! : activate $subscription now: $thankYouText = array(); $cbUser = CBuser::getInstance( $user->id ); foreach ( array_keys( $subscriptions ) as $k ) { if ( ( $reason != 'R' ) || $subscriptions[$k]->checkIfRenewable() ) { $occurrences = 1; $autorecurring_type = 0; $autorenew_type = 0; // bug #1184 fix: this was certainly wrong in backend at least, but in frontend too most likely too, as it would block from renewing imho: // $autorecurring_type = ( ( $chosenPlans[$k]->autorecurring > 0 ) ? 2 : 0 ); // $autorenew_type = ( ( $chosenPlans[$k]->autorecurring > 0 ) ? 2 : 0 ); $subscriptions[$k]->activate( $user, $subscriptionTime, true, $reason, $occurrences, $autorecurring_type, $autorenew_type ); $extraStrings = $subscriptions[$k]->substitutionStrings( true ); $thankYouText[] = trim( $cbUser->replaceUserVars( CBPTXT::Th( $subscriptions[$k]->getText( 'thankyoutextcompleted' ) ), true, true, $extraStrings, false ) ); } } if ( count( $thankYouText ) > 0 ) { return implode( '<br />', $thankYouText ); } else { return CBPTXT::Th("Chosen plan(s) can not be subscribed") . '.'; } } else { // non-free plan: // 2. add payment_item and payment_basket records: // get the most recent payment basket for $subscription $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); /* $basketLoaded = $paymentBasket->loadLatestBasketOfUserPlanSubscription( $user->id ); if ( $basketLoaded ) { $paymentBasket->delete(); $paymentBasket = new cbpaidPaymentBasket( $_CB_database ); //TBD LATER: Handle fully payment baskets as baskets, adding/replacing the content with the new items. } */ $hasAmountToPay = $paymentBasket->createAndFillCreteSubscriptionsItems( $user, $sortedSubscriptions, $prefixText, $reason, $subscriptionTime ); if ( ! $hasAmountToPay ) { $thankYouText = array(); $cbUser = CBuser::getInstance( $user->id ); foreach ( array_keys( $subscriptions ) as $k ) { $subscriptions[$k]->activate( $user, $subscriptionTime, true, $reason ); $extraStrings = $subscriptions[$k]->substitutionStrings( true ); $thankYouText[] = trim( $cbUser->replaceUserVars( CBPTXT::Th( $subscriptions[$k]->getText( 'thankyoutextcompleted' ) ), true, true, $extraStrings, false ) ); } return implode( '<br />', $thankYouText ); } if ( ( $paymentBasket->payment_status === null ) || ( $paymentBasket->payment_status == 'NotInitiated' ) ) { return $paymentBasket; } } trigger_error( '_createSubscriptionsAndPayment: Unexpected condition: no payment and no free plan', E_USER_NOTICE ); return 'Unexpected condition.'; }
/** * Gives upgrade possibilities for plans and discount in case of renewal. * Only exclusive plans can be upgraded to other exclusive plans with the same father. * * @param int $ui 1: frontend user, 2: backend admin * @param UserTable $user user being displayed * @param cbpaidSomething $subscription subscriptions being proposed for upgrade * @param float $remainingValue remaining value of the subscription (for prorate upgrades) in currency of this plan * @param float $quantity Quantity purchased * @param int $now unix time * @return array */ public function upgradePlansPossibilities( /** @noinspection PhpUnusedParameterInspection */ $ui, UserTable $user, &$subscription, $remainingValue, $quantity, $now ) { $result = array(); if ( $this->get( 'exclusive' ) == 1 ) { $plansMgr =& cbpaidPlansMgr::getInstance(); $plans =& $plansMgr->loadPublishedPlans( $user, true, 'upgrade', null ); //TBD LATER: implement restriction on owner $remainingValueCurrencies = array( $this->currency() => $remainingValue ); foreach ( $plans as $p ) { if ( ( $p->get( 'exclusive' ) == 1 ) && ( $p->id != $this->id ) && ( $p->parent == $this->parent ) ) { if ( $remainingValue == 0 ) { $pCurRemVal = 0; } else { if ( ! isset( $remainingValueCurrencies[$p->currency()] ) ) { $remainingValueCurrencies[$p->currency()] = $this->_priceConvert( $p->currency(), $remainingValue ); } $pCurRemVal = $remainingValueCurrencies[$p->currency()]; } $discountedPrice = $p->getPrice( null, $subscription, 'U', 0, $now, $pCurRemVal, $quantity ); if ( ( $discountedPrice == false ) && ( $p->get( 'auto_compute_upgrade' ) == 0 ) ) { $discountedPrice = 0; } if ( $discountedPrice !== false ) { $result[$p->id] = $discountedPrice; } } } } return $result; }
/** * parses regex match callback plan substitutions * * @param array $matches * @return string */ public function replacePlanSubstitutions( $matches ) { $planId = ( isset( $matches[1] ) ? (int) $matches[1] : null ); $text = ( isset( $matches[2] ) ? $matches[2] : null ); if ( $planId && $text ) { $user = cbUser::getMyUserDataInstance(); $plansMgr = cbpaidPlansMgr::getInstance(); $plan = $plansMgr->getPublishedPlan( $planId, $user ); if ( $plan ) { // Output CSS for displaying the plan properly: cbpaidTemplateHandler::getViewer( '', null )->outputTemplateCss( 'cbpaidsubscriptions' ); $plan->getTemplateOutoutCss(); // Get substitutions: return $plan->getPersonalized( $text, $user->id, true, true, null, false ); } } return null; }