esoTalk /controllers/ETMembersController.class.php

Language PHP Lines 302
MD5 Hash 3ea5acf9cb1ff64dc37e2492e9e5debd
Repository https://github.com/Ramir1/esoTalk.git View Raw File
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
<?php
// Copyright 2011 Toby Zerner, Simon Zerner
// This file is part of esoTalk. Please see the included license file for usage information.

if (!defined("IN_ESOTALK")) exit;

/**
 * The members controller handles the member list, online members sheet, and the creation of new members.
 *
 * @package esoTalk
 */
class ETMembersController extends ETController {


/**
 * Show the member list page.
 *
 * @param string $orderBy What to sort the members by.
 * @param mixed $start Where to start the results from. This can be:
 * 		- An integer, in which case it will be used as a numerical offset.
 * 		- pX, where X is the "page" number.
 * 		- A letter to start from, if $orderBy is "name".
 * @return void
 */
public function index($orderBy = false, $start = 0)
{
	// Check if we have permission to view the member list.
	if (!C("esoTalk.members.visibleToGuests") and !ET::$session->user) {
		$this->render404(T("message.pageNotFound"));
		return false;
	}

	// Begin constructing a query to fetch results.
	$sql = ET::SQL()->from("member m");

	// If we've limited results by a search string...
	if ($searchString = R("search")) {

		// Get an array of all groups which we can possibly filter by.
		$groups = ET::groupModel()->getAll();
		$groups[GROUP_ID_ADMINISTRATOR] = array("name" => ACCOUNT_ADMINISTRATOR);
		$groups[GROUP_ID_MEMBER] = array("name" => ACCOUNT_MEMBER);
		$groups[GROUP_ID_GUEST] = array("name" => ACCOUNT_SUSPENDED);

		// If the search string matches any group names, then we'll filter members by their account/group.
		$restrictGroup = false;
		$search = strtolower($searchString);
		foreach ($groups as $id => $group) {
			$name = $group["name"];
			if (strtolower(T("group.$name", $name)) == $search or strtolower(T("group.$name.plural", $name)) == $search) {
				$restrictGroup = $id;
				break;
			}
		}

		// Did we find any matching groups just before? If so, add a WHERE condition to the query to filter by group.
		if ($restrictGroup) {
			if ($restrictGroup < 0) $sql->where("account", $groups[$restrictGroup]["name"]);
			else $sql
				->from("member_group mg", "mg.memberId=m.memberId", "left")
				->where("mg.groupId", $restrictGroup);
		}

		// If there were no matching groups, just perform a normal LIKE search.
		else $sql
			->where("username LIKE :search")
			->bind(":search", $searchString."%");
	}

	// Create a query to get the total number of results. Clone the results one to retain the same WHERE conditions.
	$count = clone $sql;
	$count = $count
		->select("COUNT(m.memberId)")
		->exec()
		->result();

	// Make an array of possible orders for the list.
	$orders = array(
		"name" => array(T("Name"), "username ASC"),
		"posts" => array(T("Posts"), "countPosts DESC"),
		"activity" => array(T("Last active"), "lastActionTime DESC")
	);

	// If an invalid orderBy key was provided, just use the first one.
	if (!isset($orders[$orderBy])) $orderBy = reset(array_keys($orders));

	// Work out where to start the results from.
	$page = 0;
	if ($start) {

		// If we're ordering by name and the start argument is a single letter...
		if ($orderBy == "name" and strlen($start) == 1 and ctype_alpha($start)) {

			// Run a query to get the position of the first member starting with this letter.
			$start = ET::SQL()
				->select("COUNT(memberId)", "position")
				->from("member")
				->where("STRCMP(username, :username) = -1")
				->bind(":username", $start)
				->exec()
				->result();
			$start = min($count - C("esoTalk.members.membersPerPage"), $start);

		}

		// If the start argument is "pX", where X is the page number...
		elseif ($start[0] == "p") {
			$page = ltrim($start, "p");
			$start = C("esoTalk.members.membersPerPage") * ($page - 1);
		}

		// Otherwise, parse the start argument as a simple integer offset.
		else {
			$start = (int)($start);
			$page = round($start / C("esoTalk.members.membersPerPage"));
		}

		// Apply the offset to the query.
		$start = max(0, $start);
		$sql->offset($start);
	}

	// Finish constructing the query. We want to get a list of member IDs to show as the results.
	$ids = $sql
		->select("m.memberId")
		->limit(C("esoTalk.members.membersPerPage"))
		->orderBy($orders[$orderBy][1])
		->exec()
		->allRows();
	foreach ($ids as &$id) $id = $id["memberId"];

	// Finally, fetch the member data for the members with these IDs.
	if ($ids) $members = ET::memberModel()->getByIds($ids);
	else $members = array();

	// If we're doing a normal page load...
	if ($this->responseType === RESPONSE_TYPE_DEFAULT) {

		// Set the title and make sure this page isn't indexed.
		$this->title = T("Member List");
		$this->addToHead("<meta name='robots' content='noindex, noarchive'/>");

		// Work out the canonical URL for this page.
		$url = "members/$orderBy/p$page";
		$this->canonicalURL = URL($url, true);
		$this->pushNavigation("members", "members", URL($url));

		// Add JavaScript files and variables for the page to use.
		$this->addJSFile("js/scrubber.js");
		$this->addJSFile("js/members.js");
		$this->addJSVar("membersPerPage", C("esoTalk.members.membersPerPage"));
		$this->addJSVar("countMembers", $count);
		$this->addJSVar("startFrom", $start);
		$this->addJSVar("searchString", $searchString);
		$this->addJSVar("orderBy", $orderBy);

	}

	// Pass data to the view.
	$this->data("members", $members);
	$this->data("countMembers", $count);
	$this->data("startFrom", $start);
	$this->data("searchString", $searchString);
	$this->data("orders", $orders);
	$this->data("orderBy", $orderBy);

	// On an AJAX request, just render the list, and also pass back the startFrom position.
	if ($this->responseType === RESPONSE_TYPE_AJAX) {
		$this->json("startFrom", $start);
		$this->render("members/list");
	}

	else $this->render("members/index");
}


/**
 * Show the "create member" sheet, containing a form to create a new member.
 *
 * @return void
 */
public function create()
{
	// Non-admins can't do this! Suckers.
	if (!ET::$session->isAdmin()) return;

	// Set up the form.
	$form = ETFactory::make("form");
	$form->action = URL("members/create");

	// Was the cancel button pressed?
	if ($form->isPostBack("cancel"))
		$this->redirect(URL(R("return", "members")));

	// Was the "create" button pressed?
	if ($form->validPostBack("submit")) {

		// Make sure the passwords match.
		if ($form->getValue("confirm") != $form->getValue("password"))
			$form->error("confirm", T("message.passwordsDontMatch"));

		// If there were no preliminary errors, proceed to attempt to create the member with the model.
		if (!$form->errorCount()) {

			$data = array(
				"username" => $form->getValue("username"),
				"email" => $form->getValue("email"),
				"password" => $form->getValue("password"),
				"account" => ACCOUNT_MEMBER,
				"confirmedEmail" => true
			);

			$model = ET::memberModel();
			$id = $model->create($data);

			// If there were any errors, pass them back to the form.
			if ($model->errorCount()) $form->errors($model->errors());

			// Otherwise, redirect to this new member's profile.
			else $this->redirect(URL(memberURL($id, $form->getValue("username"))));

		}

	}

	$this->data("form", $form);
	$this->render("members/create");
}


/**
 * Show the "online members" sheet.
 *
 * @return void
 */
public function online()
{
	// Check if we have permission to view the online list.
	if (!C("esoTalk.members.visibleToGuests") and !ET::$session->user) {
		$this->render404(T("message.pageNotFound"));
		return false;
	}

	// Set the title and make sure this page isn't indexed.
	$this->title = T("Online Members");
	$this->addToHead("<meta name='robots' content='noindex, noarchive'/>");

	// Construct a query to get only members who are online.
	$sql = ET::SQL()
		->where((time() - ET::config("esoTalk.userOnlineExpire"))."<lastActionTime")
		->orderBy("lastActionTime DESC");

	// Pass this query to the member model and get all of these members' data.
	$members = ET::memberModel()->getWithSQL($sql);

	$this->data("members", $members);
	$this->render("members/online");
}


/**
 * Return a JSON array of up to 50 members whose usernames match a given string. This data can be used to
 * create a list of members in an autocomplete menu.
 *
 * @param string $input The string to match member usernames against.
 * @return void
 */
public function autocomplete($input = "")
{
	// Force the response type to JSON.
	$this->responseType = RESPONSE_TYPE_JSON;

	// Don't do this for strings less than three characters for performance reasons.
	if (strlen($input) < 3) return;

	// Construct a query to fetch matching members.
	$results = ET::SQL()
		->select("'member' AS type")
		->select("memberId AS id")
		->select("username AS name")
		->select("avatarFormat")
		->select("email")
		->from("member")
		->where("username LIKE :username")
		->bind(":username", $input."%")
		->orderBy("username")
		->limit(50)
		->exec()
		->allRows();

	// Loop through the results and generate avatar HTML for each one.
	foreach ($results as $k => $v) {
		$results[$k]["avatar"] = avatar($v, "thumb");
		unset($results[$k]["avatarFormat"]);
		unset($results[$k]["email"]);
	}

	$this->json("results", $results);
	$this->render();
}

}
Back to Top