Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue/1508 pagination #1541

Merged
merged 19 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions fuel/app/classes/controller/api/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,20 @@ public function post_user($user_id)
return \Service_User::update_user($user_id, $user);
}

public function get_widget_search(string $input)
public function get_instance_search(string $input, string $page_number)
{
$input = trim($input);
$input = urldecode($input);
$page_number = (int) $page_number;
//no need to search if for some reason an empty string is passed
if ($input == '') return [];
return \Materia\Widget_Instance_Manager::get_search($input);
if ($input == '')
{
return [
'pagination' => [],
'next_page' => $page_number
];
}
return \Materia\Widget_Instance_Manager::get_paginated_instance_search($input, $page_number);
}

public function get_extra_attempts(string $inst_id)
Expand Down
40 changes: 28 additions & 12 deletions fuel/app/classes/materia/api/v1.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ static public function widget_instances_get($inst_ids = null, bool $deleted = fa
*
* @return array of objects containing total_num_pages and widget instances that are visible to the user.
*/
static public function widget_paginate_instances_get($page_number = 0)
static public function widget_paginate_user_instances_get($page_number = 0)
{
if (\Service_User::verify_session() !== true) return Msg::no_login();
$data = Widget_Instance_Manager::get_paginated_for_user(\Model_User::find_current_id(), $page_number);
$data = Widget_Instance_Manager::get_paginated_instances_for_user(\Model_User::find_current_id(), $page_number);
return $data;
}

Expand Down Expand Up @@ -886,23 +886,39 @@ static public function semester_date_ranges_get()
return Utils::get_date_ranges();
}

static public function users_search($search)
/**
* Paginated search for users that match input
*
* @param string Search query
* @param string Page number
* @return array List of users
*/
static public function users_search($input, $page_number = 0)
{
if (\Service_User::verify_session() !== true) return Msg::no_login();

$user_objects = \Model_User::find_by_name_search($search);
$user_arrays = [];
$items_per_page = 50;
$offset = $items_per_page * $page_number;

// query DB for only a single page + 1 item
$displayable_items = \Model_User::find_by_name_search($input, $offset, $items_per_page + 1);

$has_next_page = sizeof($displayable_items) > $items_per_page ? true : false;

if ($has_next_page) array_pop($displayable_items);

// scrub the user models with to_array
if (count($user_objects))
foreach ($displayable_items as $key => $person)
{
foreach ($user_objects as $key => $person)
{
$user_arrays[$key] = $person->to_array();
}
$displayable_items[$key] = $person->to_array();
}

return $user_arrays;
$data = [
'pagination' => $displayable_items,
];

if ($has_next_page) $data['next_page'] = $page_number + 1;

return $data;
}
/**
* Gets information about the current user
Expand Down
67 changes: 54 additions & 13 deletions fuel/app/classes/materia/widget/instance/manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ static public function get($inst_id, $load_qset=false, $timestamp=false, $delete
return count($instances) > 0 ? $instances[0] : false;
}

static public function get_all(Array $inst_ids, $load_qset=false, $timestamp=false, bool $deleted=false): array
static public function get_all(Array $inst_ids, $load_qset=false, $timestamp=false, bool $deleted=false, $offset=0, $limit=80): array
{
if ( ! is_array($inst_ids) || count($inst_ids) < 1) return [];

Expand All @@ -27,6 +27,9 @@ static public function get_all(Array $inst_ids, $load_qset=false, $timestamp=fal
->where('id', 'IN', $inst_ids)
->and_where('is_deleted', '=', $deleted ? '1' : '0')
->order_by('created_at', 'desc')
->order_by('id', 'desc')
->offset("$offset")
->limit("$limit")
->execute()
->as_array();

Expand Down Expand Up @@ -63,7 +66,7 @@ public static function get_all_for_user($user_id, $load_qset=false)
{
$inst_ids = Perm_Manager::get_all_objects_for_user($user_id, Perm::INSTANCE, [Perm::FULL, Perm::VISIBLE]);

if ( ! empty($inst_ids)) return Widget_Instance_Manager::get_all($inst_ids, $load_qset);
if ( ! empty($inst_ids)) return self::get_all($inst_ids, $load_qset);
else return [];
}

Expand All @@ -76,22 +79,25 @@ public static function get_all_for_user($user_id, $load_qset=false)
*
* @return array of widget instances that are visible to the user.
*/
public static function get_paginated_for_user($user_id, $page_number = 0)
public static function get_paginated_instances_for_user($user_id, $page_number = 0)
{
$inst_ids = Perm_Manager::get_all_objects_for_user($user_id, Perm::INSTANCE, [Perm::FULL, Perm::VISIBLE]);
$displayable_inst = self::get_all($inst_ids);
$widgets_per_page = 80;
$total_num_pages = ceil(sizeof($displayable_inst) / $widgets_per_page);
$offset = $widgets_per_page * $page_number;
$has_next_page = $offset + $widgets_per_page < sizeof($displayable_inst) ? true : false;

// inst_ids corresponds to a single page's worth of instances
$displayable_inst = array_slice($displayable_inst, $offset, $widgets_per_page);
$items_per_page = 80;
$offset = $items_per_page * $page_number;

// query DB for only a single page of instances + 1
$displayable_items = self::get_all($inst_ids, false, false, false, $offset, $items_per_page + 1);

// if the returned number of instances is greater than a page, there's more pages
$has_next_page = sizeof($displayable_items) > $items_per_page ? true : false;

if ($has_next_page) array_pop($displayable_items);

$data = [
'pagination' => $displayable_inst
'pagination' => $displayable_items
];

if ($has_next_page) $data['next_page'] = $page_number + 1;

return $data;
Expand Down Expand Up @@ -135,20 +141,55 @@ public static function lock($inst_id)
return $locked_by == $me;
}

/**
* Widget instance paginated search results
*
* @param input search input
* @param page_number page number
*
* @return array of items related to the given input
*/
public static function get_paginated_instance_search(string $input, $page_number = 0)
{
$items_per_page = 80;
$offset = $items_per_page * $page_number;

// query DB for only a single page of instances + 1
$displayable_items = self::get_widget_instance_search($input, $offset, $items_per_page + 1);

// if the returned number of instances is greater than a page, there's more pages
$has_next_page = sizeof($displayable_items) > $items_per_page ? true : false;

if ($has_next_page) array_pop($displayable_items);

$data = [
'pagination' => $displayable_items,
];

if ($has_next_page) $data['next_page'] = $page_number + 1;

return $data;
}

/**
* Gets all widget instances related to a given input, including id or name.
*
* @param input search input
* @param offset start search at this row in results
* @param limit number of rows to include
*
* @return array of widget instances related to the given input
*/
public static function get_search(string $input): array
public static function get_widget_instance_search(string $input, int $offset = 0, int $limit = 80): array
{
$results = \DB::select()
->from('widget_instance')
->where('id', 'LIKE', "%$input%")
->or_where('name', 'LIKE', "%$input%")
->order_by('created_at', 'desc')
->order_by('id', 'desc')
->offset($offset)
->limit($limit)
->execute()
->as_array();

Expand Down
14 changes: 11 additions & 3 deletions fuel/app/classes/model/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public static function find_by_username($username)
->get_one();
}

static public function find_by_name_search($name)
static public function find_by_name_search($name, $offset = 0, $limit=80)
{
$name = preg_replace('/\s+/', '', $name); // remove spaces

Expand All @@ -108,11 +108,19 @@ static public function find_by_name_search($name)
->or_where(\DB::expr('REPLACE(CONCAT(first, last), " ", "")'), 'LIKE', "%$name%")
->or_where('email', 'LIKE', "$name%")
->and_where_close()
->limit(50)
->offset($offset)
->limit($limit)
->as_object('Model_User')
->execute();

return $matches;
// convert object to array
$list = [];
foreach ($matches as $match)
{
$list[] = $match;
}

return $list;
}

public static function validate($factory)
Expand Down
53 changes: 36 additions & 17 deletions fuel/app/tests/api/v1.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,32 @@ public function test_widget_instances_get()

}

public function test_widget_paginate_instances_get()
public function test_widget_paginate_user_instances_get()
{
// Create widget instance
$this->_as_author();
$title = "My Test Widget";
$question = 'What rhymes with harvest fests but are half as exciting (or tasty)';
$answer = 'Tests';
$qset = $this->create_new_qset($question, $answer);
$widget = $this->make_disposable_widget();

$instance = Api_V1::widget_instance_new($widget->id, $title, $qset, true);

// ----- loads author's instances --------
$output = Api_V1::widget_paginate_user_instances_get();
$this->assertIsArray($output);
$this->assertArrayHasKey('pagination', $output);
foreach ($output['pagination'] as $key => $value)
{
$this->assert_is_widget_instance($value, true);
}

// ======= AS NO ONE ========
\Auth::logout();
// ----- returns no login --------
$output = Api_V1::widget_paginate_user_instances_get();
$this->assert_invalid_login_message($output);
}

public function test_widget_instance_new()
Expand Down Expand Up @@ -1024,10 +1047,6 @@ public function test_play_logs_get()

}

public function test_paginated_play_logs_get()
{
}

public function test_score_summary_get()
{
// ======= AS NO ONE ========
Expand Down Expand Up @@ -1522,10 +1541,10 @@ public function test_users_search_as_student()

$output = Api_V1::users_search('droptables');
$this->assertIsArray($output);
$this->assertCount(2, $output);
$this->assert_is_user_array($output[0]);
$this->assertFalse(array_key_exists('password', $output));
$this->assertFalse(array_key_exists('login_hash', $output));
$this->assertIsArray($output['pagination']);
$this->assert_is_user_array($output['pagination'][0]);
$this->assertFalse(array_key_exists('password', $output['pagination']));
$this->assertFalse(array_key_exists('login_hash', $output['pagination']));
}

public function test_users_search_as_author()
Expand All @@ -1538,10 +1557,10 @@ public function test_users_search_as_author()

$output = Api_V1::users_search('droptables');
$this->assertIsArray($output);
$this->assertCount(2, $output);
$this->assert_is_user_array($output[0]);
$this->assertFalse(array_key_exists('password', $output));
$this->assertFalse(array_key_exists('login_hash', $output));
$this->assertIsArray($output['pagination']);
$this->assert_is_user_array($output['pagination'][0]);
$this->assertFalse(array_key_exists('password', $output['pagination']));
$this->assertFalse(array_key_exists('login_hash', $output['pagination']));
}

public function test_users_search_as_super_user()
Expand All @@ -1554,10 +1573,10 @@ public function test_users_search_as_super_user()

$output = Api_V1::users_search('droptables');
$this->assertIsArray($output);
$this->assertCount(2, $output);
$this->assert_is_user_array($output[0]);
$this->assertFalse(array_key_exists('password', $output[0]));
$this->assertFalse(array_key_exists('login_hash', $output[0]));
$this->assertIsArray($output['pagination']);
$this->assert_is_user_array($output['pagination'][0]);
$this->assertFalse(array_key_exists('password', $output['pagination']));
$this->assertFalse(array_key_exists('login_hash', $output['pagination']));
}

protected function assert_is_semester_rage($semester)
Expand Down
Loading
Loading