<?php

/*
This example code is for installing on your PHP-based website or application
to check that the current session should be granted access to the URL it
is attempting to access, and if not, to divert them to the appropriate waiting room.

This is sample code that works directly with cURL, we would expect you to adapt
this example so that it works with the front controller of your application, and
your preferred http library.

Since the purpose of a waiting room is to protect your application, you should
run this code at the earliest opportuity, before invoking the rest of your 
application code to reduce load across your system.
*/

// start a timer so that we can track page performance. 
$chTimer=-microtime(true);

// Configure the API call to check the CrowdHandler Session
define('CH_API_BASE_URL', "api.crowdhandler.com/v1/");
define('CH_PUBLIC_KEY', 'YOUR KEY HERE');
define('CH_FAIL_MODE', 'safe'); // can be 'safe', 'trust', or the slug of a known waiting room you would like to use as a safety net.

$chParams = new stdClass;
$chParams->url = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$chParams->ip = $_SERVER['REMOTE_ADDR'];
$chParams->agent = $_SERVER['HTTP_USER_AGENT'];
$chParams->lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];

/* 
the parameters above check the URL the user is requesting against rooms on your account.
if you were writing an integration for an application with a known waiting room
you could check that room specifically with $chParams->slug, instead of matching via the URL.
*/

/*
look for the CrowdHandler token in the url (CrowdHandler will pass it when redirecting the user to this site)
failing that check the cookies, as this may not be the first request from this session.
*/

$chToken = isset($_GET['ch-id']) ? $_GET['ch-id'] : isset($_COOKIE['ch-id']) ? $_COOKIE['ch-id'] : null;

if($chToken) {
  // have a token; GET request incorporates token
  $chApiResource = CH_API_BASE_URL."requests/$chToken?".http_build_query($chParams);
  $ch = curl_init($chApiResource);
} else { 
  // no token; POST will create new token
  $chApiResource = CH_API_BASE_URL."requests/";
  $ch = curl_init($chApiResource);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($chParams));
}
curl_setopt($ch, CURLOPT_HTTPHEADER, ['content-type: application/json', 'x-api-key: '.CH_PUBLIC_KEY]); // authentication header
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);

// Make the call, and process the response
try {
  $jsonResponse = curl_exec($ch);
  if(curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) {
    $phpResponse = json_decode($jsonResponse);
    $chResult = $phpResponse->result;
    /*
    set a secure session cookie, so we can revalidate them on the next request
    note; even if we presented an expired/invalid token, we will have received a new one 
    so we should always trust the token that comes back over then one we sent.
    */
    setcookie('ch-id', $chResult->token, 0, '/', '', true);
    
    // check if this user should have access to this url
    if($chResult->promoted != 1) {
      /*
      user should not have access to this url right now.
      they might be new, and we don't have capacity
      or they could be known, and have attempted to access the url without first being promoted 
      Either way, we send them to the appropriate waiting room by setting a temporary redirect header.
      */
      header('location: https://wait.crowdhandler.com/'.$chResult->slug.'?ch-id='.$chResult->token, true, 302);
      exit;
    }
  }
  else {
    throw new Exception('API returned HTTP error');
  }
} catch (Exception $e) {
  // request failed, or HTTP error received
  switch(CH_FAIL_MODE) {
    case 'safe':
      // send user to unknown waiting room to be handled by CrowdHandler.
      header('location: https://wait.crowdhandler.com/?'.http_build_query(['url'=>$chParams->url,'publicKey'=>CH_PUBLIC_KEY]), true, 302);
      exit;
    case 'trust':
      // trust user and continue flow of your application
      break;      
    default:
      // send to specified waiting room (CH_FAIL_MODE is the slug)
      header('location: https://wait.crowdhandler.com/'.CH_FAIL_MODE);
  }
}

/*
We've handled the request, and confirmed this user does not need to wait.
this is where you do your thing, sending control back to the normal flow of your application.
the html output below is just to provide you with some test/debug info whilst you try it out. 
*/

?>
<html>
<head>
    <title>Crowdhandler PHP Integration</title>
</head>
<body>
  <h1>CrowdHandler PHP Integration</h1>

  <p>You requested the url <code><?=$chParams->url ?></code> with token <code><?=$chToken ? $chToken:'none' ?></code><p>

  <p>CrowdHandler sent this response:</p>

  <code><pre><?=$jsonResponse ?></pre></code>

</body>
<?php

/*  
now you've finished handled your user's request you can make a second API call
to send performance information to CrowdHandler.

CrowdHandler will anaylze this data to use in moderating exit rates from the
waiting rooms attached to this domain.
*/

$chTimer+=microtime(true);

$chParams = new stdClass;
$chParams->time = $chTimer;
/*
we presume if you got this far you are serving your user a 200 response, 
but if that's not the case, and you are able to log HTTP error codes this will 
improve CrowdHandler's performance monitoring. 
*/
$chParams->httpCode = 200;

// set up the API call to update CrowdHandler with the performance time.
$chApiResource = CH_API_BASE_URL.'requests/'.$chResult->token;
$ch = curl_init($chApiResource);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['content-type: application/json', 'x-api-key: '.CH_PUBLIC_KEY]); // authentication header
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($chParams));
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch,CURLOPT_TIMEOUT, 2);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

// execute call
$void = curl_exec($ch);

// we're done.
curl_close($ch);

?>