<?php
/*
	Question2Answer by Gideon Greenspan and contributors
	http://www.question2answer.org/

	File: qa-external-example/qa-external-users.php
	Description: Example of how to integrate with your own user database


	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	More about this license: http://www.question2answer.org/license.php
*/


/*
	=========================================================================
	THIS FILE ALLOWS YOU TO INTEGRATE WITH AN EXISTING USER MANAGEMENT SYSTEM
	=========================================================================

	It is used if QA_EXTERNAL_USERS is set to true in qa-config.php.
*/

if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
	header('Location: ../');
	exit;
}


/**
 * ==========================================================================
 * YOU MUST MODIFY THIS FUNCTION *BEFORE* Q2A CREATES ITS DATABASE
 * ==========================================================================
 *
 * You should return the appropriate MySQL column type to use for the userid,
 * for smooth integration with your existing users. Allowed options are:
 *
 * SMALLINT, SMALLINT UNSIGNED, MEDIUMINT, MEDIUMINT UNSIGNED, INT, INT UNSIGNED,
 * BIGINT, BIGINT UNSIGNED or VARCHAR(x) where x is the maximum length.
 */
function qa_get_mysql_user_column_type()
{
	// Set this before anything else

	return null;

	/*
		Example 1 - suitable if:

		* You use textual user identifiers with a maximum length of 32

		return 'VARCHAR(32)';
	*/

	/*
		Example 2 - suitable if:

		* You use unsigned numerical user identifiers in an INT UNSIGNED column

		return 'INT UNSIGNED';
	*/
}


/**
 * ===========================================================================
 * YOU MUST MODIFY THIS FUNCTION, BUT CAN DO SO AFTER Q2A CREATES ITS DATABASE
 * ===========================================================================
 *
 * You should return an array containing URLs for the login, register and logout pages on
 * your site. These URLs will be used as appropriate within the Q2A site.
 *
 * You may return absolute or relative URLs for each page. If you do not want one of the links
 * to show, omit it from the array, or use null or an empty string.
 *
 * If you use absolute URLs, then return an array with the URLs in full (see example 1 below).
 *
 * If you use relative URLs, the URLs should start with $relative_url_prefix, followed by the
 * relative path from the root of the Q2A site to your login page. Like in example 2 below, if
 * the Q2A site is in a subdirectory, $relative_url_prefix.'../' refers to your site root.
 *
 * Now, about $redirect_back_to_url. Let's say a user is viewing a page on the Q2A site, and
 * clicks a link to the login URL that you returned from this function. After they log in using
 * the form on your main site, they want to automatically go back to the page on the Q2A site
 * where they came from. This can be done with an HTTP redirect, but how does your login page
 * know where to redirect the user to? The solution is $redirect_back_to_url, which is the URL
 * of the page on the Q2A site where you should send the user once they've successfully logged
 * in. To implement this, you can add $redirect_back_to_url as a parameter to the login URL
 * that you return from this function. Your login page can then read it in from this parameter,
 * and redirect the user back to the page after they've logged in. The same applies for your
 * register and logout pages. Note that the URL you are given in $redirect_back_to_url is
 * relative to the root of the Q2A site, so you may need to add something.
 */
function qa_get_login_links($relative_url_prefix, $redirect_back_to_url)
{
	// Until you edit this function, don't show login, register or logout links

	return array(
		'login' => null,
		'register' => null,
		'logout' => null
	);

	/*
		Example 1 - using absolute URLs, suitable if:

		* Your Q2A site:       http://qa.mysite.com/
		* Your login page:     http://www.mysite.com/login
		* Your register page:  http://www.mysite.com/register
		* Your logout page:    http://www.mysite.com/logout

		return array(
			'login' => 'http://www.mysite.com/login',
			'register' => 'http://www.mysite.com/register',
			'logout' => 'http://www.mysite.com/logout',
		);
	*/

	/*
		Example 2 - using relative URLs, suitable if:

		* Your Q2A site:       http://www.mysite.com/qa/
		* Your login page:     http://www.mysite.com/login.php
		* Your register page:  http://www.mysite.com/register.php
		* Your logout page:    http://www.mysite.com/logout.php

		return array(
			'login' => $relative_url_prefix.'../login.php',
			'register' => $relative_url_prefix.'../register.php',
			'logout' => $relative_url_prefix.'../logout.php',
		);
	*/

	/*
		Example 3 - using relative URLs, and implementing $redirect_back_to_url

		In this example, your pages login.php, register.php and logout.php should read in the
		parameter $_GET['redirect'], and redirect the user to the page specified by that
		parameter once they have successfully logged in, registered or logged out.

		return array(
			'login' => $relative_url_prefix.'../login.php?redirect='.urlencode('qa/'.$redirect_back_to_url),
			'register' => $relative_url_prefix.'../register.php?redirect='.urlencode('qa/'.$redirect_back_to_url),
			'logout' => $relative_url_prefix.'../logout.php?redirect='.urlencode('qa/'.$redirect_back_to_url),
		);
	*/
}


/**
 * ===========================================================================
 * YOU MUST MODIFY THIS FUNCTION, BUT CAN DO SO AFTER Q2A CREATES ITS DATABASE
 * ===========================================================================
 *
 * qa_get_logged_in_user()
 *
 * You should check (using $_COOKIE, $_SESSION or whatever is appropriate) whether a user is
 * currently logged in. If not, return null. If so, return an array with the following elements:
 *
 * - userid: a user id appropriate for your response to qa_get_mysql_user_column_type()
 * - publicusername: a user description you are willing to show publicly, e.g. the username
 * - email: the logged in user's email address
 * - passsalt: (optional) password salt specific to this user, used for form security codes
 * - level: one of the QA_USER_LEVEL_* values below to denote the user's privileges:
 *
 * QA_USER_LEVEL_BASIC, QA_USER_LEVEL_EDITOR, QA_USER_LEVEL_ADMIN, QA_USER_LEVEL_SUPER
 *
 * To indicate that the user is blocked you can also add an element 'blocked' with the value true.
 * Blocked users are not allowed to perform any write actions such as voting or posting.
 *
 * The result of this function will be passed to your other function qa_get_logged_in_user_html()
 * so you may add any other elements to the returned array if they will be useful to you.
 *
 * Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
 * Q2A, you can also use the various qa_db_* functions to run queries.
 *
 * In order to access the admin interface of your Q2A site, ensure that the array element 'level'
 * contains QA_USER_LEVEL_ADMIN or QA_USER_LEVEL_SUPER when you are logged in.
 */
function qa_get_logged_in_user()
{
	// Until you edit this function, nobody is ever logged in

	return null;

	/*
		Example 1 - suitable if:

		* You store the login state and user in a PHP session
		* You use textual user identifiers that also serve as public usernames
		* Your database is shared with the Q2A site
		* Your database has a users table that contains emails
		* The administrator has the user identifier 'admin'

		session_start();

		if (isset($_SESSION['is_logged_in'])) {
			$userid = $_SESSION['logged_in_userid'];

			$result = qa_db_read_one_assoc(qa_db_query_sub(
				'SELECT email FROM users WHERE id=$',
				$userid
			));

			if (is_array($result)) {
				return array(
					'userid' => $userid,
					'publicusername' => $userid,
					'email' => $result['email'],
					'level' => ($userid == 'admin') ? QA_USER_LEVEL_ADMIN : QA_USER_LEVEL_BASIC
				);
			}
		}

		return null;
	*/

	/*
		Example 2 - suitable if:

		* You store a session ID inside a cookie
		* You use numerical user identifiers
		* Your database is shared with the Q2A site
		* Your database has a sessions table that maps session IDs to users
		* Your database has a users table that contains usernames, emails and a flag for admin privileges

		if (isset($_COOKIE['sessionid'])) {
			$result = qa_db_read_one_assoc(qa_db_query_sub(
				'SELECT userid, username, email, admin_flag FROM users WHERE userid=(SELECT userid FROM sessions WHERE sessionid=#)',
				$_COOKIE['sessionid']
			));

			if (is_array($result)) {
				return array(
					'userid' => $result['userid'],
					'publicusername' => $result['username'],
					'email' => $result['email'],
					'level' => $result['admin_flag'] ? QA_USER_LEVEL_ADMIN : QA_USER_LEVEL_BASIC
				);
			}
		}

		return null;
	*/
}


/**
 * ===========================================================================
 * YOU MUST MODIFY THIS FUNCTION, BUT CAN DO SO AFTER Q2A CREATES ITS DATABASE
 * ===========================================================================
 *
 * qa_get_user_email($userid)
 *
 * Return the email address for user $userid, or null if you don't know it.
 *
 * Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
 * Q2A, you can also use the various qa_db_* functions to run queries.
 */
function qa_get_user_email($userid)
{
	// Until you edit this function, always return null

	return null;

	/*
		Example 1 - suitable if:

		* Your database is shared with the Q2A site
		* Your database has a users table that contains emails

		$result = qa_db_read_one_assoc(qa_db_query_sub(
			'SELECT email FROM users WHERE userid=#',
			$userid
		));

		if (is_array($result))
			return $result['email'];

		return null;
	*/
}


/**
 * ===========================================================================
 * YOU MUST MODIFY THIS FUNCTION, BUT CAN DO SO AFTER Q2A CREATES ITS DATABASE
 * ===========================================================================
 *
 * qa_get_userids_from_public($publicusernames)
 *
 * You should take the array of public usernames in $publicusernames, and return an array which
 * maps valid usernames to internal user ids. For each element of this array, the username should be
 * in the key, with the corresponding user id in the value. If your usernames are case- or accent-
 * insensitive, keys should contain the usernames as stored, not necessarily as in $publicusernames.
 *
 * Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
 * Q2A, you can also use the various qa_db_* functions to run queries. If you access this database or
 * any other, try to use a single query instead of one per user.
 */
function qa_get_userids_from_public($publicusernames)
{
	// Until you edit this function, always return null

	return null;

	/*
		Example 1 - suitable if:

		* You use textual user identifiers that are also shown publicly

		$publictouserid = array();

		foreach ($publicusernames as $publicusername)
			$publictouserid[$publicusername] = $publicusername;

		return $publictouserid;
	*/

	/*
		Example 2 - suitable if:

		* You use numerical user identifiers
		* Your database is shared with the Q2A site
		* Your database has a users table that contains usernames

		$publictouserid = array();

		if (count($publicusernames)) {
			$escapedusernames = array();
			foreach ($publicusernames as $publicusername)
				$escapedusernames[] = "'" . qa_db_escape_string($publicusername) . "'";

			$results = qa_db_read_all_assoc(qa_db_query_raw(
				'SELECT username, userid FROM users WHERE username IN (' . implode(',', $escapedusernames) . ')'
			));

			foreach ($results as $result)
				$publictouserid[$result['username']] = $result['userid'];
		}

		return $publictouserid;
	*/
}


/**
 * ===========================================================================
 * YOU MUST MODIFY THIS FUNCTION, BUT CAN DO SO AFTER Q2A CREATES ITS DATABASE
 * ===========================================================================
 *
 * qa_get_public_from_userids($userids)
 *
 * This is exactly like qa_get_userids_from_public(), but works in the other direction.
 *
 * You should take the array of user identifiers in $userids, and return an array which maps valid
 * userids to public usernames. For each element of this array, the userid you were given should
 * be in the key, with the corresponding username in the value.
 *
 * Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
 * Q2A, you can also use the various qa_db_* functions to run queries. If you access this database or
 * any other, try to use a single query instead of one per user.
 */
function qa_get_public_from_userids($userids)
{
	// Until you edit this function, always return null

	return null;

	/*
		Example 1 - suitable if:

		* You use textual user identifiers that are also shown publicly

		$useridtopublic = array();

		foreach ($userids as $userid)
			$useridtopublic[$userid] = $userid;

		return $useridtopublic;
	*/

	/*
		Example 2 - suitable if:

		* You use numerical user identifiers
		* Your database is shared with the Q2A site
		* Your database has a users table that contains usernames

		$useridtopublic = array();

		if (count($userids)) {
			$escapeduserids = array();
			foreach ($userids as $userid)
				$escapeduserids[] = "'" . qa_db_escape_string($userid) . "'";

			$results = qa_db_read_all_assoc(qa_db_query_raw(
				'SELECT username, userid FROM users WHERE userid IN (' . implode(',', $escapeduserids) . ')'
			));

			foreach ($results as $result)
				$useridtopublic[$result['userid']] = $result['username'];
		}

		return $useridtopublic;
	*/
}


/**
 * ==========================================================================
 * YOU MAY MODIFY THIS FUNCTION, BUT THE DEFAULT BELOW WILL WORK OK
 * ==========================================================================
 *
 * qa_get_logged_in_user_html($logged_in_user, $relative_url_prefix)
 *
 * You should return HTML code which identifies the logged in user, to be displayed next to the
 * logout link on the Q2A pages. This HTML will only be shown to the logged in user themselves.
 * Note: the username MUST be escaped with htmlspecialchars() for general output, or urlencode()
 * for link URLs.
 *
 * $logged_in_user is the array that you returned from qa_get_logged_in_user(). Hopefully this
 * contains enough information to generate the HTML without another database query, but if not,
 * call qa_db_connection() to get the connection to the Q2A database.
 *
 * $relative_url_prefix is a relative URL to the root of the Q2A site, which may be useful if
 * you want to include a link that uses relative URLs. If the Q2A site is in a subdirectory of
 * your site, $relative_url_prefix.'../' refers to your site root (see example 1).
 *
 * If you don't know what to display for a user, you can leave the default below. This will
 * show the public username, linked to the Q2A profile page for the user.
 */
function qa_get_logged_in_user_html($logged_in_user, $relative_url_prefix)
{
	// By default, show the public username linked to the Q2A profile page for the user

	$publicusername = $logged_in_user['publicusername'];

	return '<a href="' . qa_path_html('user/' . $publicusername) . '" class="qa-user-link">' . htmlspecialchars($publicusername) . '</a>';

	/*
		Example 1 - suitable if:

		* Your Q2A site:       http://www.mysite.com/qa/
		* Your user pages:     http://www.mysite.com/user/[username]

		$publicusername = $logged_in_user['publicusername'];

		return '<a href="' . htmlspecialchars($relative_url_prefix . '../user/' . urlencode($publicusername)) .
			'" class="qa-user-link">' . htmlspecialchars($publicusername) . '</a>';
	*/

	/*
		Example 2 - suitable if:

		* Your Q2A site:       http://qa.mysite.com/
		* Your user pages:     http://www.mysite.com/[username]/
		* 16x16 user photos:   http://www.mysite.com/[username]/photo-small.jpg

		$publicusername = $logged_in_user['publicusername'];

		return '<a href="http://www.mysite.com/' . htmlspecialchars(urlencode($publicusername)) . '/" class="qa-user-link">' .
			'<img src="http://www.mysite.com/' . htmlspecialchars(urlencode($publicusername)) . '/photo-small.jpg" ' .
			'style="width:16px; height:16px; border:none; margin-right:4px;">' . htmlspecialchars($publicusername) . '</a>';
	*/
}


/**
 * ==========================================================================
 * YOU MAY MODIFY THIS FUNCTION, BUT THE DEFAULT BELOW WILL WORK OK
 * ==========================================================================
 *
 * qa_get_users_html($userids, $should_include_link, $relative_url_prefix)
 *
 * You should return an array of HTML to display for each user in $userids. For each element of
 * this array, the userid should be in the key, with the corresponding HTML in the value.
 * Note: the username MUST be escaped with htmlspecialchars() for general output, or urlencode()
 * for link URLs.
 *
 * Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
 * Q2A, you can also use the various qa_db_* functions to run queries. If you access this database or
 * any other, try to use a single query instead of one per user.
 *
 * If $should_include_link is true, the HTML may include links to user profile pages.
 * If $should_include_link is false, links should not be included in the HTML.
 *
 * $relative_url_prefix is a relative URL to the root of the Q2A site, which may be useful if
 * you want to include links that uses relative URLs. If the Q2A site is in a subdirectory of
 * your site, $relative_url_prefix.'../' refers to your site root (see example 1).
 *
 * If you don't know what to display for a user, you can leave the default below. This will
 * show the public username, linked to the Q2A profile page for each user.
 */
function qa_get_users_html($userids, $should_include_link, $relative_url_prefix)
{
	// By default, show the public username linked to the Q2A profile page for each user

	$useridtopublic = qa_get_public_from_userids($userids);

	$usershtml = array();

	foreach ($userids as $userid) {
		$publicusername = $useridtopublic[$userid];

		$usershtml[$userid] = htmlspecialchars($publicusername);

		if ($should_include_link)
			$usershtml[$userid] = '<a href="' . qa_path_html('user/' . $publicusername) . '" class="qa-user-link">' . $usershtml[$userid] . '</a>';
	}

	return $usershtml;

	/*
		Example 1 - suitable if:

		* Your Q2A site:       http://www.mysite.com/qa/
		* Your user pages:     http://www.mysite.com/user/[username]

		$useridtopublic = qa_get_public_from_userids($userids);

		foreach ($userids as $userid) {
			$publicusername = $useridtopublic[$userid];

			$usershtml[$userid] = htmlspecialchars($publicusername);

			if ($should_include_link) {
				$usershtml[$userid] = '<a href="' . htmlspecialchars($relative_url_prefix . '../user/' . urlencode($publicusername)) .
					'" class="qa-user-link">' . $usershtml[$userid] . '</a>';
			}
		}

		return $usershtml;
	*/

	/*
		Example 2 - suitable if:

		* Your Q2A site:       http://qa.mysite.com/
		* Your user pages:     http://www.mysite.com/[username]/
		* User photos (16x16): http://www.mysite.com/[username]/photo-small.jpg

		$useridtopublic = qa_get_public_from_userids($userids);

		foreach ($userids as $userid) {
			$publicusername = $useridtopublic[$userid];

			$usershtml[$userid] = '<img src="http://www.mysite.com/' . htmlspecialchars(urlencode($publicusername)) . '/photo-small.jpg" ' .
				'style="width:16px; height:16px; border:0; margin-right:4px;">' . htmlspecialchars($publicusername);

			if ($should_include_link) {
				$usershtml[$userid] = '<a href="http://www.mysite.com/' . htmlspecialchars(urlencode($publicusername)) .
					'/" class="qa-user-link">' . $usershtml[$userid] . '</a>';
			}
		}

		return $usershtml;
	*/
}


/**
 * ==========================================================================
 * YOU MAY MODIFY THIS FUNCTION, BUT THE DEFAULT BELOW WILL WORK OK
 * ==========================================================================
 *
 * qa_avatar_html_from_userid($userid, $size, $padding)
 *
 * You should return some HTML for displaying the avatar of $userid on the page.
 * If you do not wish to show an avatar for this user, return null.
 *
 * $size contains the maximum width and height of the avatar to be displayed, in pixels.
 *
 * If $padding is true, the HTML you return should render to a square of $size x $size pixels,
 * even if the avatar is not square. This can be achieved using CSS padding - see function
 * qa_get_avatar_blob_html(...) in qa-app-format.php for an example. If $padding is false,
 * the HTML can render to anything which would fit inside a square of $size x $size pixels.
 *
 * Note that this function may be called many times to render an individual page, so it is not
 * a good idea to perform a database query each time it is called. Instead, you can use the fact
 * that before qa_avatar_html_from_userid(...) is called, qa_get_users_html(...) will have been
 * called with all the relevant users in the array $userids. So you can pull out the information
 * you need in qa_get_users_html(...) and cache it in a global variable, for use in this function.
 */
function qa_avatar_html_from_userid($userid, $size, $padding)
{
	// Show no avatars by default

	return null;

	/*
		Example 1 - suitable if:

		* All your avatars are square
		* Your Q2A site:       http://www.mysite.com/qa/
		* Your avatar images:  http://www.mysite.com/avatar/[userid]-[size]x[size].jpg

		$htmlsize = (int)$size;

		return '<img src="http://www.mysite.com/avatar/' . htmlspecialchars($userid) . '-' . $htmlsize . 'x' . $htmlsize . '.jpg" ' .
			'width="' . $htmlsize . '" height="' . $htmlsize . '" class="qa-avatar-image" alt=""/>';
	*/
}


/**
 * ==========================================================================
 * YOU MAY MODIFY THIS FUNCTION, BUT THE DEFAULT BELOW WILL WORK OK
 * ==========================================================================
 *
 * qa_user_report_action($userid, $action)
 *
 * Informs you about an action by user $userid that modified the database, such as posting,
 * voting, etc... If you wish, you may use this to log user activity or monitor for abuse.
 *
 * Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
 * Q2A, you can also use the various qa_db_* functions to run queries.
 *
 * $action will be a string (such as 'q_edit') describing the action. These strings will match the
 * first $event parameter passed to the process_event(...) function in event modules. In fact, you might
 * be better off just using a plugin with an event module instead, since you'll get more information.
 *
 * FYI, you can get the IP address of the user from qa_remote_ip_address().
 */
function qa_user_report_action($userid, $action)
{
	// Do nothing by default
}
