/**
	 * Displays the "Content Access Denied View
	 * 
	 * @param  UserTable                   $user
	 * @param  CBplug_cbpaidsubscriptions  $baseClass
	 * @return string
	 */
	public function display( & $user, /** @noinspection PhpUnusedParameterInspection */ &$baseClass ) {
		global $_CB_framework;

		if ( ! is_callable( array( 'cbpaidBot', 'getInstance' ) ) ) {
			return CBPTXT::T("CBSubs CbpaidSubsBot is not installed, enabled and running or CBSubs Content integration plugin is not up to date. Please ask site administrator to do so.");
		}

		$cbpaidBot				=	cbpaidBot::getInstance();

		$userId						=	$_CB_framework->myId();
		$accesstype					=	cbGetParam( $_GET, 'accesstype' );
		$accessvalue				=	cbGetParam( $_GET, 'accessvalue' );
		$accessurl					=	cbGetParam( $_GET, 'accessurl' );
		switch ( $accesstype ) {
			case 'components':
				$option				=	$accessvalue;
				$accessPlans		=	$cbpaidBot->checkAccess( $userId, $option, 'cpaycontent_components', null, true );
				if ( is_array( $accessPlans ) ) {
					$result			=	array( 'can', CBPTXT::T("component") );	// CBPTXT::T("You can access to this component with following plans: ");													// . implode( ', ', $accessPlans );
					$access			=	false;
				} elseif ( $accessPlans === true ) {
					$result			=	array( 'have', CBPTXT::T("component") );	// CBPTXT::T("You have access now to this component !");
					$access			=	true;
				} else {
					$result			=	array( 'unknown', CBPTXT::T("component"), $accessPlans );	// 'Unknown component access result: ' . var_export( $accessPlans, true );
					$access			=	false;
				}
				break;

			case 'menus':
				$itemid				=	(int) $accessvalue;
				$accessPlans		=	$cbpaidBot->checkAccess( $userId, $itemid, 'cpaycontent_menus' , null, true );
				if ( is_array( $accessPlans ) ) {
					$result			=	array( 'can', CBPTXT::T("menu") );	// CBPTXT::T("You can access to this menu with following plans: ");														// . implode( ', ', $accessPlans );
					$access			=	false;
				} elseif ( $accessPlans === true ) {
					$result			=	array( 'have', CBPTXT::T("menu") );	// CBPTXT::T("You have access now to this menu !");
					$access			=	true;
				} else {
					$result			=	array( 'unknown', CBPTXT::T("menu"), $accessPlans );	// 'Unknown menu access result: ' . var_export( $accessPlans, true );
					$access			=	false;
				}
				break;

			case 'urls':
				$getPostArray		=	$this->_decodeArrayUrl( $accessurl );
				$postsMissingInGetToFindPlans	=	array();
				$accessPlans		=	$cbpaidBot->checkAccessUrl( $userId, $getPostArray, $getPostArray, $postsMissingInGetToFindPlans, 'cpaycontent_urls', true );
				if ( is_array( $accessPlans ) ) {
					$result			=	array( 'can', CBPTXT::T("location") );	// CBPTXT::T("You can access to this location with following plans: ");													// . implode( ', ', $accessPlans );
					$access			=	false;
				} elseif ( $accessPlans === true ) {
					$result			=	array( 'have', CBPTXT::T("location") );	// CBPTXT::T("You have access now to this location !");
					$access			=	true;
				} else {
					$result			=	array( 'unknown', CBPTXT::T("location"), $accessPlans );	// 'Unknown location access result: ' . var_export( $accessPlans, true );
					$access			=	false;
				}
				break;

			case 'sections':					// section list:
				$sectionId			=	(int) $accessvalue;
				$accessPlans		=	$cbpaidBot->checkAccess( $userId, $sectionId, 'cpaycontent_sections', 'cpaycontent_sections_list', true );
				if ( is_array( $accessPlans ) ) {
					$result			=	array( 'can', CBPTXT::T("content section") );	// CBPTXT::T("You can access to this content section with following plans: ");												// . implode( ', ', $accessPlans );
					$access			=	false;
				} elseif ( $accessPlans === true ) {
					$result			=	array( 'have', CBPTXT::T("content section") );	// CBPTXT::T("You have access now to this content section !");
					$access			=	true;
				} else {
					$result			=	array( 'unknown', CBPTXT::T("content section"), $accessPlans );	// 'Unknown content section access result: ' . var_export( $accessPlans, true );
					$access			=	false;
				}
				break;

			case 'categories':
				$categoryId			=	(int) $accessvalue;
				$accessPlans		=	$cbpaidBot->checkAccess( $userId, $categoryId, 'cpaycontent_categories', 'cpaycontent_categories_list', true );

				$sectionId			=	$cbpaidBot->getSectionOfCategory( $categoryId );
				if ( $sectionId ) {
					$accessPlansSection	=	$cbpaidBot->checkAccess( $userId, $sectionId, 'cpaycontent_sections', 'cpaycontent_sections_list', true );
				} else {
					$accessPlansSection	=	array();
				}

				if ( is_array( $accessPlans ) ) {
					if ( is_array( $accessPlansSection ) ) {
						$result		=	array( 'can', CBPTXT::T("content category") . ' ' . CBPTXT::T("or"). ' ' . CBPTXT::T("content section in which this content category is located") );	// CBPTXT::T("You can access to this content category with following plans: ")												// . implode( ', ', $accessPlans )
																			//.	CBPTXT::T("You can access to the whole content section enclosing this content category with following plans: ");			// . implode( ', ', $accessPlansSection );
						$access		=	false;
					} elseif ( $accessPlansSection === null ) {
						$result		=	array( 'can', CBPTXT::T("content category") );	// CBPTXT::T("You can access to this content category with following plans: ");											// . implode( ', ', $accessPlans );
						$access		=	false;
					} elseif ( $accessPlansSection === true ) {
						$result		=	array( 'have', CBPTXT::T("content section in which this content category is located") );	// CBPTXT::T("You have access now to the whole content section in which this content category is located !");
						$access		=	true;
					} else {
						$result		=	array( 'unknown', CBPTXT::T("content section"), $accessPlansSection );	// 'Unknown content section access result: ' . var_export( $accessPlans, true );
						$access		=	false;
					}
				} elseif ( $accessPlans === null ) {
					if ( is_array( $accessPlansSection ) ) {
						$result		=	array( 'can', CBPTXT::T("content section in which this content category is located") );	//CBPTXT::T("You can access to the whole content section enclosing this content category with following plans: ");			// . implode( ', ', $accessPlansSection );
						$access		=	false;
					} elseif ( $accessPlansSection === null ) {
						$result		=	CBPTXT::T("These content categories are not under category or section access control");
						$access		=	true;
					} elseif ( $accessPlansSection === true ) {
						$result		=	array( 'have', CBPTXT::T("content section in which this content category is located") );	//CBPTXT::T("You have access now to the whole content section in which this content category is located !");
						$access		=	true;
					} else {
						$result		=	array( 'unknown', CBPTXT::T("content section"), $accessPlansSection );	// 'Unknown content section access result: ' . var_export( $accessPlans, true );
						$access		=	false;
					}
				} elseif ( $accessPlans === true ) {
					$result			=	array( 'have', CBPTXT::T("content category") );	// CBPTXT::T("You have access now to this content categories !");
					$access			=	true;
				} else {
					$result			=	array( 'unknown', CBPTXT::T("content category"), $accessPlans );	// 'Unknown content categories access result: ' . var_export( $accessPlans, true );
					$access			=	false;
				}
				break;

			case 'contentdisplay':
				$contentId			=	(int) $accessvalue;

				global $_CB_database;

				$row				=	null;
				$sql				=	'SELECT * FROM #__content WHERE id = ' . (int) $contentId;
				$_CB_database->setQuery( $sql );
				$contentExists		=	$_CB_database->loadObject( $row );
				if ( $contentExists ) {
					/** @var StdClass $row */
					$_cbACL			=&	cbpaidBotAclApi::getInstance();
					$accessPlans	=	$_cbACL->_cb_checkMultiAcl_Ok_or_Plans( $_CB_framework->myId(), $row->id, isset( $row->catid ) ? $row->catid : null, isset( $row->sectionid ) ? $row->sectionid : null, -1 );
					if ( is_array( $accessPlans ) ) {
						$accessPlansWrite	=	$_cbACL->_cb_checkMultiAcl( $_CB_framework->myId(), $row->id, isset( $row->catid ) ? $row->catid : null, isset( $row->sectionid ) ? $row->sectionid : null, count( $_cbACL->cbContentAclRights ) -1 );
						if ( $accessPlansWrite === true ) {
							$result	=	CBPTXT::T("You have access to this content item");
							$access	=	true;
						} elseif ( is_array( $accessPlansWrite ) && ( count( $accessPlansWrite ) > 0 ) ) {
							$result	=	array( 'can', CBPTXT::T("content item") );	// CBPTXT::T("You can access to this article with following plans: ")														// . implode( ', ', $accessPlans ) 
																		//.	CBPTXT::T("You can access with write access to this article with following plans: ");									// . implode( ', ', $accessPlansWrite );
							$access	=	false;
						} else {
							$result	=	array( 'can', CBPTXT::T("content item") );	// CBPTXT::T("You can access to this article with following plans: ");														// . implode( ', ', $accessPlans );
							$access	=	false;
						}
					} elseif ( $accessPlans === true ) {
						$result		=	array( 'have', CBPTXT::T("content item") );	// CBPTXT::T("You have access now to this article !");
						$access		=	true;
					} else {
						$result		=	array( 'unknown', CBPTXT::T("content item"), $accessPlans );	// 'Unknown access result: ' . var_export( $accessPlans, true );
						$access		=	false;
					}
				} else {
					$result			=	CBPTXT::T("This content item does not exist");
					$access			=	true;
					$accessPlans	=	array();
				}
				break;

			default:
				// Hacking or PCI-DSS intrusion trial:
				$result			=	CBPTXT::T("This redirection URL is invalid.");
				$access			=	true;
				$accessPlans	=	array();
				break;
		}
		if ( $access ) {
			if ( is_array( $result ) ) {
				switch ( $result[0] ) {
					case 'have':
						$return		=	sprintf( CBPTXT::Th("You have now access to this %s"), $result[1] );
						//TBD later in a safe way (FS#259): or with $_SESSION
						// $realUrl	=	base64_decode( $accessurl );
						// $return		.=	'<a href="' . $_CB_framework->getCfg( 'live_site' ) . '/index.php?' . htmlspecialchars( $realUrl ) . '">Click here to access</a>';
						break;

					default:
						$return		=	"Unknown access allowed result: " . var_export( $result, true );
						break;
				}
			} else {
				$return				=	$result;
			}
		} else {
			if ( is_array( $result ) ) {
				switch ( $result[0] ) {
					case 'can':
						if ( count( $accessPlans ) > 0 ) {
							$params	=&	cbpaidApp::settingsParams();
							$subTxt	=	CBPTXT::T( $params->get( 'subscription_name', 'subscription' ) );
							$result	=	sprintf( CBPTXT::Th("You can access this %s with following %s plans:"), $result[1], $subTxt );

							// CB login return-to after login URL:
							if ( $accessurl ) {
								global $cbSpecialReturnAfterLogin;
								$url =	base64_decode( $accessurl );
								if ( ! preg_match( '#https?://#i', $url ) ) {
									$cbSpecialReturnAfterLogin	=	'******' . $url;
								}
							}

							// We need to also display child plans of the $accessPlans as some might be needed (mandatory):
							$plans	=	cbpaidSubscriptionsMgr::getInstance()->getUpgradablePlansWithChildrensForPlans( $accessPlans, $user );
							$return	=	cbpaidControllerOffer::displaySpecificPlans( $plans, null, $user, $result );
						} else {
							$return	=	sprintf( CBPTXT::Th("You can not access this %s") . '.', $result[1] );
						}
						break;

					case 'unknown':
						$return		=	sprintf( CBPTXT::Th("Unknown %s access result: %s") . '.', $result[1], var_export( $result[2], true ) );
						break;

					default:
						$return		=	"Unknown access allowed result" . ': ' . var_export( $result, true );
						break;
				}
			} else {
				$return				=	$result;
			}
		}
		return $return;
	}
/**
 * Trigger for onBeforeDisplayContent
 * @param  object     $row
 * @param  JRegistry  $articleParams
 * @param  int        $page
 * @return void
 */
function cbpaidsubsbot_onBeforeDisplayContent( &$row, &$articleParams, /** @noinspection PhpUnusedParameterInspection */ $page ) {
	global $_CB_framework;

	$cbpaidBot					=	cbpaidBot::getInstance();

	if ( $cbpaidBot->paidsubsManager === null ) {
			return;
	}
	cbpaidErrorHandler::on();

	if ( isset( $row->id ) ) {
		$myId					=	$_CB_framework->myId();
		$_cbACL					=&	cbpaidBotAclApi::getInstance();
		$access					=	$_cbACL->_cb_checkMultiAcl( $myId, $row->id, isset( $row->catid ) ? $row->catid : null, isset( $row->sectionid ) ? $row->sectionid : null, -1 );

		if ( $access === false ) {

			if ( $_cbACL->_cb_checkMultiAcl( $myId, $row->id, isset( $row->catid ) ? $row->catid : null, isset( $row->sectionid ) ? $row->sectionid : null, count( $_cbACL->cbContentAclRights ) -1 ) !== true ) {

				// allow usage of <!-- !CBPAIDaccessCheck --> to NOT control the item
				if( ! ( isset( $row->text ) && strstr( $row->text, " !CBPAIDaccessCheck " ) ) ) {

					$params							=&	cbpaidApp::settingsParams();

					// allow access to someone who is unrestricted:
					if ( ! $cbpaidBot->hasAccessAnyway( $myId ) ) {

						// var_dump($row);
							// show/hides the intro text
						//	if ( $params->get( 'introtext'  ) ) {
						//		$row->text = $row->introtext. ( $params->get( 'intro_only' ) ? '' : chr(13) . chr(13) . $row->fulltext);
						//	} else {
						//		$row->text = $row->fulltext;
						//	}
						$redirectVars				=	array( 'accesstype' => 'contentdisplay', 'accessvalue' => (int) $row->id );
						$redirectVars['accessurl']	=	cbpaidsubsbot_encodeArrayUrl( $_GET );
			
						$redirectUrl				=	'index.php?option=com_comprofiler&task=pluginclass&plugin=cbpaidsubscriptions&do=accessdenied' . getCBprofileItemid( false);		// &Itemid= ???
						foreach ( $redirectVars as $k => $v ) {
							$redirectUrl			.=	'&' . urlencode( $k ) . '=' . urlencode( $v );
						}
			
						// translate message:
						cbpaidApp::loadLang();
						$subTxt						=	CBPTXT::T( $params->get( 'subscription_name', 'subscription' ) );

						$allowAccessToIntro			=	$params->get( 'integration_cpaycontent_allowIntro', '1' );
						// If access to intro is NO (0), or DEPENDS (2) but there is no main full text, then we do not allow to see anything:
						$disallowAccessToAnyText	=	( $allowAccessToIntro == 0 ) || ( ( $allowAccessToIntro == 2 ) && ! ( isset( $row->readmore ) ? $row->readmore != 0 : trim( strip_tags( $row->fulltext ) ) != '' ) );

						if ( $disallowAccessToAnyText ) {
							$messageTxt				=	'<span class="cbpaidContentAccessDenied">' . sprintf( CBPTXT::Th( 'To read this article, a %s is needed: Click here to subscribe' ), $subTxt ) . '</span>';
						} else {
							$messageTxt				=	'<span class="cbpaidContentAccessDenied">' . sprintf( CBPTXT::Th( 'To read more, a %s is needed: Click here to subscribe' ), $subTxt ) . '</span>';
						}

						if ( ( ($cbpaidBot->option == 'com_content' || $cbpaidBot->option == 'content') && ( ( $cbpaidBot->task == 'view' ) || ( $cbpaidBot->task == '' ) ) && ( $cbpaidBot->view != 'frontpage' ) && ( $cbpaidBot->view != 'featured' ) ) )  {
							// article view:
							if ( $disallowAccessToAnyText ) {
								// option=com_content&task=view
								cbRedirect( cbSef( $redirectUrl, false ), sprintf( CBPTXT::T("Access to this content is not allowed without %s"), $subTxt ) );
								return;
							}
							// 1.5: needed for title links:
							$row->readmore_link		=	cbSef( $redirectUrl );
							if ( ( $cbpaidBot->cbCmsVersion == 1 ) && ( in_array( $cbpaidBot->view, array( 'frontpage', 'section', 'category' ) ) ) ) {
								// 1.5: (section and category are for layout=blog (section blog), but as section layout just displays categories, it is ok to not check for that)
								$row->readmore_register	=	false;
								$articleParams->set( 'readmore', $messageTxt );
							} else {
								$row->text			=	$row->introtext;

								if ( trim( strip_tags( $row->fulltext ) ) ) {
									$row->text			.=	'<a href="' . cbSef( $redirectUrl ) . '">' . $messageTxt . '</a>';
								}
							}
						} else {
							//	$row->text			=	$row->text . $message;
							// 1.0:
							$row->link_text			=	$messageTxt;
							$row->link_on			=	cbSef( $redirectUrl );
							$articleParams->set( 'intro_only', 1 );
							if ( $cbpaidBot->cbCmsVersion == 1 ) {
								$articleParams->set( 'readmore', $messageTxt );
							} else {
								$articleParams->set( 'readmore', 1 );
							}
							// 1.5: needed for title links:
							$row->readmore_link		=	cbSef( $redirectUrl );
							if ( $disallowAccessToAnyText ) {
								$row->introtext		=	'';
								$row->text			=	'';
								$row->readmore		=	1;
							}
							if ( class_exists( 'JDatabaseQuery' ) ) {
								// 1.6:
								$row->alternative_readmore	=	'</a>' . '<a class="cbregPayToViewRedirectLink" href="' . cbSef( $redirectUrl ) . '">' . $messageTxt . ' ';		// Space is for case of article title in readmore link following. Ideally should be ': ' in that case only.
							}
						}
					}
				}
			}
		}

		// run cbsubs plan substitutions after access readmore access checks
		if ( isset( $row->title ) ) {
			$row->title			=	preg_replace_callback( '/\{cbsubs:plan:(\d+):(.*?)\}/s', array( $cbpaidBot, 'replacePlanSubstitutions' ), $row->title );
		}

		if ( isset( $row->introtext ) ) {
			$row->introtext		=	preg_replace_callback( '/\{cbsubs:plan:(\d+):(.*?)\}/s', array( $cbpaidBot, 'replacePlanSubstitutions' ), $row->introtext );
		}

		if ( isset( $row->fulltext ) ) {
			$row->fulltext		=	preg_replace_callback( '/\{cbsubs:plan:(\d+):(.*?)\}/s', array( $cbpaidBot, 'replacePlanSubstitutions' ), $row->fulltext );
		}

		if ( isset( $row->text ) ) {
			$row->text			=	preg_replace_callback( '/\{cbsubs:plan:(\d+):(.*?)\}/s', array( $cbpaidBot, 'replacePlanSubstitutions' ), $row->text );
		}
	}
	cbpaidErrorHandler::off();

}