/**
 * Adds an admin user
 *
 * @param array $reg_data
 * @param \PDO $link
 * @return array
 */
function register_admin_user($reg_data, $link)
{
    $lang = $reg_data['lang'];
    /** @noinspection PhpIncludeInspection */
    require dirname(__FILE__) . "/../../languages/{$lang}/admin/admregtxt.php";
    if (strlen($reg_data['user']) < USER_MINLENGTH) {
        return array('error' => REG_ADM_USR_USER_TOO_SHORT);
    }
    if (strlen($reg_data['user']) > USER_MAXLENGTH) {
        return array('error' => REG_ADM_USR_USER_TOO_LONG);
    }
    if (strlen($reg_data['password']) < PASS_MINLENGTH) {
        return array('error' => REG_ADM_USR_PASS_TOO_SHORT);
    }
    if ($reg_data['password'] !== $reg_data['password2']) {
        return array('error' => REG_ADM_USR_PASS_NO_MATCH);
    }
    if (($email = filter_var($reg_data['email'], FILTER_VALIDATE_EMAIL)) === false) {
        return array('error' => REG_ADM_USR_MUST_PROVIDE_VALID_EMAIL);
    }
    $use_password_hash = defined('SYNAPP_USE_PASSWORD_HASH_AUTHENTICATION') && (SYNAPP_USE_PASSWORD_HASH_AUTHENTICATION === true || is_string(SYNAPP_USE_PASSWORD_HASH_AUTHENTICATION) && (trim(strtolower(SYNAPP_USE_PASSWORD_HASH_AUTHENTICATION)) === 'on' || trim(strtolower(SYNAPP_USE_PASSWORD_HASH_AUTHENTICATION)) === 'true' || trim(strtolower(SYNAPP_USE_PASSWORD_HASH_AUTHENTICATION)) === '1')) ? true : false;
    if ($use_password_hash) {
        $password = password_hash($reg_data['password'], PASSWORD_DEFAULT);
    } else {
        $password = hash('sha256', mt_rand() . '$' . $reg_data['password'] . NORAINBOW_SALT);
    }
    $sql = "INSERT INTO `synadmin` ( `uuid`, `user`, `password`, `email`, `lang` ) VALUES ( :uuid, :user , :password , :email , :lang )";
    $stmt = $link->prepare($sql);
    $v5uuid = \synapp\info\tools\uuid\uuid::v5(\synapp\info\tools\uuid\uuid::v4(), SYNAPP_MAIL_DOMAIN);
    $stmt->bindValue(':uuid', $v5uuid, PDO::PARAM_STR);
    $stmt->bindValue(':user', $reg_data['user'], PDO::PARAM_STR);
    $stmt->bindValue(':password', $password, PDO::PARAM_STR);
    $stmt->bindValue(':email', $email, PDO::PARAM_STR);
    $stmt->bindValue(':lang', $reg_data['lang'], PDO::PARAM_STR);
    if ($stmt->execute()) {
        return array('uuid' => $v5uuid);
    } else {
        error_log($link->errorInfo());
        return array('error' => REG_ADM_COULDNT_PERFORM_DATABASE_OPERATION);
    }
}
 /**
  * Processes an action on raffle collection.
  *
  * @param null|array $request
  * @throws Exception
  * @return array
  */
 private function processRaffleAction($request = null)
 {
     if ($request === null) {
         $request = $this->request;
     }
     $out = array();
     $out['subtitle'] = _('(Listing raffles)');
     $data = null;
     //check login
     if (!isset($this->access_token)) {
         throw new Exception('Unauthenticated request.', 401);
     }
     $this->adminDAO = isset($this->adminDAO) ? $this->adminDAO : new AdminDAO($this->client_id, $this->client_secret, $this->admin_redirect_uri, null, null, null, null, null, $this->debug);
     $authResponse = $this->adminDAO->authenticate(null, null, $this->adminDAO->getAccessToken());
     if (isset($authResponse['authUrl'])) {
         throw new Exception("Auth error: Invalid admin access token.", 500);
     }
     $adminClient = $this->adminDAO->getClient();
     $tableIds = $this->adminDAO->getTableIds();
     $adminId = $this->adminDAO->getAdminId();
     $this->user = isset($this->user) ? $this->user : new User($this->client_id, $this->client_secret, $this->redirect_uri, $this->access_token, null, null, null, $this->debug);
     $authResponse = $this->user->authenticate(null, null, $this->access_token);
     if (isset($authResponse['authUrl'])) {
         if (!$this->webapp) {
             throw new Exception("Authentication required (token found but expired/revoked).", 401);
         } else {
             return $this->processUserAction(array('collection' => 'user', 'action' => 'logout'));
         }
     }
     $userId = $this->user->requestUserId();
     $isAdmin = $adminId === $userId ? true : false;
     $this->raffleDAO = isset($this->raffleDAO) ? $this->raffleDAO : new RaffleDAO($tableIds, null, $adminClient, $this->debug);
     $this->raffle = isset($this->raffle) ? $this->raffle : new Raffle($this->raffleDAO, $userId, $isAdmin);
     $request['raffleid'] = isset($request['raffleid']) ? $request['raffleid'] : (isset($request['resource']) ? trim($request['resource'], '/') : null);
     switch (isset($request['action']) ? $request['action'] : '') {
         case 'list':
             $filterArray = $this->getListRaffleFilterArray($userId, $isAdmin, $request);
             $data = $this->raffle->getList($filterArray);
             break;
         case 'create':
             if (!isset($request['description'])) {
                 throw new Exception('Must specify a raffle description', 400);
             }
             $data = $this->raffle->create($request['description'], $userId);
             break;
         case 'delete':
             if (!isset($request['raffleid']) || !uuid::is_valid($request['raffleid'])) {
                 throw new Exception('Must specify a raffleid to delete', 400);
             }
             $data = $this->raffle->delete($request['raffleid']);
             break;
         case 'join':
             if (!isset($request['raffleid']) || !uuid::is_valid($request['raffleid'])) {
                 throw new Exception('Must specify a raffleid to join', 400);
             }
             $data = $this->raffle->join($request['raffleid'], isset($request['comment']) ? $request['comment'] : '', $userId);
             break;
         case 'leave':
             if (!isset($request['raffleid']) || !uuid::is_valid($request['raffleid'])) {
                 throw new Exception('Must specify a raffleid to leave', 400);
             }
             $data = $this->raffle->leave($request['raffleid'], $userId);
             break;
         case 'check':
             if (!isset($request['raffleid']) || !uuid::is_valid($request['raffleid'])) {
                 throw new Exception('Must specify a raffleid to check', 400);
             }
             $data = $this->raffle->check($request['raffleid']);
             break;
         case 'open':
             if (!isset($request['raffleid']) || !uuid::is_valid($request['raffleid'])) {
                 throw new Exception('Must specify a raffleid to open', 400);
             }
             $data = $this->raffle->updateStatus($request['raffleid'], 'open');
             break;
         case 'close':
             if (!isset($request['raffleid']) || !uuid::is_valid($request['raffleid'])) {
                 throw new Exception('Must specify a raffleid to close', 400);
             }
             $data = $this->raffle->updateStatus($request['raffleid'], 'closed');
             break;
         case 'raffle':
             if (!isset($request['raffleid']) || !uuid::is_valid($request['raffleid'])) {
                 throw new Exception('Must specify a raffleid to raffle', 400);
             }
             $data = $this->raffle->raffle($request['raffleid'], isset($request['limit']) && intval($request['limit']) > 0 ? intval($request['limit']) : null);
             break;
         default:
             throw new Exception('The request does not contain a valid action.', 404);
     }
     $out['data'] = $data;
     return $out;
 }
 /**
  * @param $description
  * @param $userId
  * @param null $created
  * @param string $privacy
  * @param string $status
  * @param null $raffleId
  * @param null $tableId
  * @param null $fusionTablesService
  * @throws Exception
  * @return stdClass
  */
 public function addRaffle($description, $userId, $created = null, $privacy = null, $status = null, $raffleId = null, $tableId = null, $fusionTablesService = null)
 {
     if ($privacy === null) {
         $privacy = 'public';
     } else {
         $privacy = $this->escape_mysql_string($privacy);
     }
     if ($status === null) {
         $status = 'closed';
     } else {
         $status = $this->escape_mysql_string($status);
     }
     if ($created === null) {
         $created = date("Y-m-d H:i:s");
     } else {
         $created = $this->escape_mysql_string($created);
     }
     if ($raffleId === null) {
         $raffleId = uuid::v5(uuid::v4(), 'synapp\\info\\tools\\gplusraffle');
     } else {
         $raffleId = $this->escape_mysql_string($raffleId);
     }
     if ($tableId === null || $tableId === 'raffles') {
         $tableId = $this->escape_mysql_string($this->tableIds['raffles']);
     } else {
         $tableId = $this->escape_mysql_string($tableId);
     }
     $userId = $this->escape_mysql_string($userId);
     $description = $this->escape_mysql_string($description);
     if ($fusionTablesService === null) {
         $fusionTablesService = $this->fusionTablesService;
     }
     // create new raffle with creatorid = $userId
     $sql = "INSERT INTO {$tableId} " . "('raffleid','raffledescription','creatorid','created','privacy','status') " . "VALUES ('{$raffleId}', '{$description}', '{$userId}', '{$created}', '{$privacy}', '{$status}')";
     $result = $fusionTablesService->query->sql($sql);
     if (isset($result->columns) && is_array($result->columns) && $result->columns[0] === 'rowid' && isset($result->rows) && is_array($result->rows) && count($result->rows) === 1) {
         $resultObject = new stdClass();
         $resultObject->columns = array('raffleid', 'raffledescription', 'creatorid', 'created', 'privacy', 'status');
         $resultObject->rows = array(array($raffleId, $description, $userId, $created, $privacy, $status));
         return $resultObject;
     } else {
         throw new Exception("Couldn't create raffle with id {$raffleId}", 500);
     }
 }
If we're signed in we can go ahead and retrieve
the ID token, which is part of the bundle of
data that is exchange in the authenticate step
- we only need to do a network call if we have
to retrieve the Google certificate to verify it,
and that can be cached.
 ************************************************/
if ($client->getAccessToken() && !$client->isAccessTokenExpired()) {
    $_SESSION['access_token'] = $client->getAccessToken();
    $token_data = '';
    //$client->verifyIdToken()->getAttributes();
    $tableSchema = array('raffles' => array('raffleid' => 'STRING', 'raffledescription' => 'STRING', 'creatorid' => 'STRING', 'created' => 'DATETIME', 'privacy' => 'STRING', 'status' => 'STRING'), 'participants' => array('raffleid' => 'STRING', 'participantid' => 'STRING', 'comment' => 'STRING', 'joined' => 'DATETIME'), 'winners' => array('raffleid' => 'STRING', 'winnerid' => 'STRING', 'raffled' => 'DATETIME'));
    $plusService = new Google_Service_Plus($client);
    $person = $plusService->people->get('me');
    $uuid = new uuid();
    $raffleids = array(uuid::v5(uuid::v4(), 'synapp\\info\\tools\\gplusraffle'), uuid::v5(uuid::v4(), 'synapp\\info\\tools\\gplusraffle'), uuid::v5(uuid::v4(), 'synapp\\info\\tools\\gplusraffle'), uuid::v5(uuid::v4(), 'synapp\\info\\tools\\gplusraffle'));
    $insertQueries = array(array('tableName' => 'raffles', 'sql' => " ('raffleid','raffledescription','creatorid','created','privacy','status') " . "VALUES ('{$raffleids['0']}', 'test raffle 1','{$person->id}','" . date("Y-m-d H:i:s") . "','public','closed')"), array('tableName' => 'raffles', 'sql' => " ('raffleid','raffledescription','creatorid','created','privacy','status') " . "VALUES ('{$raffleids['1']}', 'test raffle 2','{$person->id}','" . date("Y-m-d H:i:s") . "','public','closed')"), array('tableName' => 'raffles', 'sql' => " ('raffleid','raffledescription','creatorid','created','privacy','status') " . "VALUES ('{$raffleids['2']}', 'test raffle 3','{$person->id}','" . date("Y-m-d H:i:s") . "','public','closed')"), array('tableName' => 'raffles', 'sql' => " ('raffleid','raffledescription','creatorid','created','privacy','status') " . "VALUES ('{$raffleids['3']}', 'test raffle 4','{$person->id}','" . date("Y-m-d H:i:s") . "','public','closed')"), array('tableName' => 'participants', 'sql' => " ('raffleid','participantid','comment','joined') " . "VALUES ('{$raffleids['0']}', '{$person->id}', 'Comment 1','" . date("Y-m-d H:i:s") . "')"), array('tableName' => 'participants', 'sql' => " ('raffleid','participantid','joined') " . "VALUES ('{$raffleids['1']}', '{$person->id}', 'Comment 2','" . date("Y-m-d H:i:s") . "')"), array('tableName' => 'participants', 'sql' => " ('raffleid','participantid','joined') " . "VALUES ('{$raffleids['2']}', '{$person->id}', 'Comment 3','" . date("Y-m-d H:i:s") . "')"), array('tableName' => 'participants', 'sql' => " ('raffleid','participantid','joined') " . "VALUES ('{$raffleids['3']}', '{$person->id}', 'Comment 4','" . date("Y-m-d H:i:s") . "')"), array('tableName' => 'winners', 'sql' => " ('raffleid','winnerid','raffled') " . "VALUES ('{$raffleids['0']}', '{$person->id}','" . date("Y-m-d H:i:s") . "')"), array('tableName' => 'winners', 'sql' => " ('raffleid','winnerid','raffled') " . "VALUES ('{$raffleids['1']}', '{$person->id}','" . date("Y-m-d H:i:s") . "')"), array('tableName' => 'winners', 'sql' => " ('raffleid','winnerid','raffled') " . "VALUES ('{$raffleids['2']}', '{$person->id}','" . date("Y-m-d H:i:s") . "')"), array('tableName' => 'winners', 'sql' => " ('raffleid','winnerid','raffled') " . "VALUES ('{$raffleids['3']}', '{$person->id}','" . date("Y-m-d H:i:s") . "')"));
    $selectQueries = array(array('tableName' => 'raffles', 'sql' => ""), array('tableName' => 'participants', 'sql' => ""), array('tableName' => 'winners', 'sql' => ""), array('tableName' => 'raffles', 'sql' => " WHERE raffleid='{$raffleids['0']}'"), array('tableName' => 'raffles', 'sql' => " WHERE raffleid!='{$raffleids['0']}'"));
    $fusionTablesService = new Google_Service_Fusiontables($client);
    $errors = array();
    $tableids = array();
    foreach ($tableSchema as $tableName => $columns) {
        $tableColumns = array();
        foreach ($columns as $columnName => $columnType) {
            $column = new Google_Service_Fusiontables_Column();
            $column->setName($columnName);
            $column->setType($columnType);
            $tableColumns[] = $column;
        }
        $table = new Google_Service_Fusiontables_Table();
        $table->setName($tableName);