integer, // total number of results * limit => integer, // how many results are returned * offset => integer, // starting from which result * results => array( // the result records * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array(...), * ), * ); */ function search_user($query_string, $limit, $offset = 0, $data = array()) { $plugin = get_config('searchplugin'); safe_require('search', $plugin); $results = call_static_method(generate_class_name('search', $plugin), 'search_user', $query_string, $limit, $offset, $data); if ($results['data']) { foreach ($results['data'] as &$result) { $result['name'] = display_name($result); $result['url'] = profile_url($result); } } return $results; } /* * The elastic search plug-in is for now only used in the "Universal Search" page. * Search is performed using the internal plug-in in all other case. * This might change in the future. */ function search_all($query_string, $limit, $offset = 0, $data = array(), $type = null) { if (record_exists('search_installed', 'name', 'elasticsearch', 'active', 1)) { safe_require('search', 'elasticsearch'); $plugin = 'elasticsearch'; $results = call_static_method(generate_class_name('search', $plugin), 'search_all', $query_string, $limit, $offset, $data, $type); return $results; } } /* * Institutional admin queries: * * These are only used to populate user lists on the Institution * Members page. They may return users who are not in the same * institution as the logged in institutional admin, so they should * return names only, not email addresses. */ function get_institutional_admin_search_results($search, $limit) { $institution = new StdClass; $institution->name = $search->institution; foreach (array('member', 'requested', 'invitedby', 'lastinstitution') as $p) { $institution->{$p} = $search->{$p}; } $results = institutional_admin_user_search($search->query, $institution, $limit); if ($results['count']) { foreach ($results['data'] as &$r) { $r['name'] = $r['firstname'] . ' ' . $r['lastname'] . ' (' . $r['username'] . ')'; if (!empty($r['studentid'])) { $r['name'] .= ' (' . $r['studentid'] . ')'; } } } return $results; } function institutional_admin_user_search($query, $institution, $limit) { $plugin = get_config('searchplugin'); safe_require('search', $plugin); return call_static_method(generate_class_name('search', $plugin), 'institutional_admin_search_user', $query, $institution, $limit); } /** * Pull two-word phrases out of a query for matching against first,last names. * * This function comes from Drupal's search module, with some small changes. */ function parse_name_query($text) { $words = array(); $fullnames = array(); // Tokenize query string preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $text, $matches, PREG_SET_ORDER); if (count($matches) < 1) { return NULL; } // Classify tokens foreach ($matches as $match) { // Strip off phrase quotes if ($match[1]{0} == '"') { $phrase = preg_replace('/\s\s+/', ' ', strtolower(substr($match[1], 1, -1))); $phraselist = explode(' ', $phrase); if (count($phraselist) == 2) { $fullnames[] = $phraselist; } else { $words = array_merge($words, array($phrase)); } } else { $words = array_merge($words, array(strtolower($match[1]))); } } return array($words, $fullnames); } function get_admin_user_search_results($search, $offset, $limit) { $plugin = get_config('searchplugin'); safe_require('search', $plugin); $constraints = array(); if ($plugin == 'internal') { // For the internal plugin, just pass the raw query through as a string, it // is parsed in the plugin. $queries = $search->query; } else { // In admin search, the search string is interpreted as either a // name search or an email search depending on its contents $queries = array(); if (!empty($search->query)) { list($words, $fullnames) = parse_name_query($search->query); foreach ($words as $word) { if (strpos($word, '@') !== false) { $queries[] = array( 'field' => 'email', 'type' => 'contains', 'string' => $word ); } else { $queries[] = array( 'field' => 'firstname', 'type' => 'contains', 'string' => $word ); $queries[] = array( 'field' => 'lastname', 'type' => 'contains', 'string' => $word ); $queries[] = array( 'field' => 'username', 'type' => 'contains', 'string' => $word ); $queries[] = array( 'field' => 'preferredname', 'type' => 'contains', 'string' => $word ); } } foreach ($fullnames as $n) { $constraints[] = array( 'field' => 'firstname', 'type' => 'contains', 'string' => $n[0] ); $constraints[] = array( 'field' => 'lastname', 'type' => 'contains', 'string' => $n[1] ); } } } if (!empty($search->f)) { $constraints[] = array('field' => 'firstname', 'type' => 'starts', 'string' => $search->f); } if (!empty($search->l)) { $constraints[] = array('field' => 'lastname', 'type' => 'starts', 'string' => $search->l); } if (!empty($search->loggedin) && $search->loggedin !== 'any') { if ($search->loggedin == 'never') { $constraints[] = array('field' => 'lastlogin', 'type' => 'equals', 'string' => null); } else if ($search->loggedin == 'ever') { $constraints[] = array('field' => 'lastlogin', 'type' => 'notequals', 'string' => null); } else if ($search->loggedin == 'since') { $constraints[] = array('field' => 'lastlogin', 'type' => 'greaterthan', 'string' => $search->loggedindate); } else if ($search->loggedin == 'notsince') { $constraints[] = array('field' => 'lastlogin', 'type' => 'lessthanequal', 'string' => $search->loggedindate); } } // Filter by export queue items if (!empty($search->exportqueue)) { $exportqueueusers = get_column_sql('SELECT usr FROM {export_queue}'); if (empty($exportqueueusers)) { // use a fake id number so that the query's in function will return no results $exportqueueusers = array(-1); } $constraints[] = array( 'field' => 'exportqueue', 'type' => 'in', 'string' => array_unique($exportqueueusers), ); } // Filter by archived submissions if (!empty($search->archivedsubmissions)) { $archivesubmissionsusers = get_column_sql('SELECT usr FROM {export_archive} e JOIN {archived_submissions} a ON a.archiveid = e.id'); if (empty($archivesubmissionsusers)) { // use a fake id number so that the query's in function will return no results $archivesubmissionsusers = array(-1); } $constraints[] = array( 'field' => 'archivesubmissions', 'type' => 'in', 'string' => array_unique($archivesubmissionsusers), ); } // Filter by duplicate emails if (!empty($search->duplicateemail)) { $duplicateemailartefacts = get_column_sql(' SELECT id FROM {artefact} WHERE artefacttype = \'email\' AND LOWER(title) IN ( SELECT LOWER(title) FROM {artefact} WHERE artefacttype = \'email\' GROUP BY LOWER(title) HAVING count(id) > 1 )'); if ($duplicateemailartefacts === false || !is_array($duplicateemailartefacts)) { $duplicateemailartefacts = array(); } $constraints[] = array( 'field' => 'duplicateemail', 'type' => 'in', 'string' => $duplicateemailartefacts ); } // Filter by viewable institutions: global $USER; if (!$USER->get('admin') && !$USER->get('staff')) { $allowed = array_merge($USER->get('admininstitutions'), $USER->get('staffinstitutions')); if (empty($search->institution)) { $search->institution = 'all'; } if ($search->institution == 'all' || !isset($allowed[$search->institution])) { $constraints[] = array( 'field' => 'institution', 'type' => 'in', 'string' => $allowed, ); } else { $constraints[] = array( 'field' => 'institution', 'type' => 'equals', 'string' => $search->institution, ); } } else if (!empty($search->institution) && $search->institution != 'all') { $constraints[] = array('field' => 'institution', 'type' => 'equals', 'string' => $search->institution); } $results = call_static_method( generate_class_name('search', $plugin), 'admin_search_user', $queries, $constraints, $offset, $limit, $search->sortby, $search->sortdir ); if ($results['count']) { $isadmin = $USER->get('admin'); $admininstitutions = $USER->get('admininstitutions'); foreach ($results['data'] as &$result) { $result['name'] = display_name($result); if (!empty($result['institutions'])) { $result['institutions'] = array_combine($result['institutions'],$result['institutions']); } // Show all user's emails if searching for duplicate emails if (!empty($search->duplicateemail)) { $emails = get_records_sql_array(' SELECT title, (CASE WHEN id IN (' . join(',', array_map('db_quote', $duplicateemailartefacts)) . ') THEN 1 ELSE 0 END) AS duplicated FROM {artefact} a WHERE a.artefacttype = ? AND a.owner = ?', array('email', $result['id'])); if (is_array($emails)) { for ($i = 0; $i < count($emails); $i++) { // Move primary email to the beginning of $emails if ($emails[0]->title == $result['email']) { break; } if ($emails[$i]->title == $result['email']) { $e = $emails[0]; $emails[0] = $emails[$i]; $emails[$i] = $e; break; } } } else { throw new EmailException('An User must have at least one email!'); } $result['email'] = $emails; } if ($isadmin) { continue; } // Remove email address when viewed by staff if (!$hideemail = (empty($admininstitutions) || empty($result['institutions']))) { $commoninstitutions = array_intersect($admininstitutions, $result['institutions']); $hideemail = $hideemail || empty($commoninstitutions); } if ($hideemail) { unset($result['email']); } } } return $results; } function build_admin_user_search_results($search, $offset, $limit) { global $USER, $THEME; $wantedparams = array('query', 'f', 'l', 'sortby', 'sortdir', 'loggedin', 'loggedindate', 'duplicateemail', 'institution'); $params = array(); foreach ($search as $k => $v) { if (!in_array($k, $wantedparams)) { continue; } if (!empty($v)) { $params[] = $k . '=' . $v; } } $searchurl = get_config('wwwroot') . 'admin/users/search.php?' . join('&', $params) . '&limit=' . $limit; $results = get_admin_user_search_results($search, $offset, $limit); $pagination = build_pagination(array( 'id' => 'admin_usersearch_pagination', 'class' => 'center', 'url' => $searchurl, 'count' => $results['count'], 'setlimit' => true, 'limit' => $limit, 'jumplinks' => 8, 'numbersincludeprevnext' => 2, 'offset' => $offset, 'datatable' => 'searchresults', 'searchresultsheading' => 'resultsheading', 'jsonscript' => 'admin/users/search.json.php', )); $cols = array( 'icon' => array( 'template' => 'admin/users/searchiconcolumn.tpl', 'class' => 'center', 'accessible' => get_string('profileicon'), ), 'firstname' => array( 'name' => get_string('firstname'), 'sort' => true, 'template' => 'admin/users/searchfirstnamecolumn.tpl', ), 'lastname' => array( 'name' => get_string('lastname'), 'sort' => true, 'template' => 'admin/users/searchlastnamecolumn.tpl', ), 'preferredname' => array( 'name' => get_string('displayname'), 'sort' => true, ), 'username' => array( 'name' => get_string('username'), 'sort' => true, 'template' => 'admin/users/searchusernamecolumn.tpl', ), 'email' => array( 'name' => get_string('email'), 'sort' => true, ), ); if ($search->duplicateemail) { $cols['email'] = array( 'name' => get_string('emails'), 'sort' => true, 'help' => true, 'helplink' => get_help_icon('core', 'admin', 'usersearch', 'email'), 'template' => 'admin/users/searchemailcolumn.tpl', ); } $institutions = get_records_assoc('institution', '', '', '', 'name,displayname'); if (count($institutions) > 1) { $cols['institution'] = array( 'name' => get_string('institution'), 'sort' => false, 'template' => 'admin/users/searchinstitutioncolumn.tpl', ); } $cols['authname'] = array( 'name' => get_string('authentication'), 'sort' => true, ); $cols['lastlogin'] = array( 'name' => get_string('lastlogin', 'admin'), 'sort' => true, 'template' => 'strftimedatetime.tpl', ); $cols['select'] = array( 'headhtml' => '' . get_string('All') . ' ' . get_string('none') . '', 'template' => 'admin/users/searchselectcolumn.tpl', 'class' => 'center nojs-hidden-table-cell', 'accessible' => get_string('bulkselect'), ); if (!$USER->get('admin') && !$USER->is_institutional_admin()) { unset($cols['email']); if (!get_config('staffreports')) { unset($cols['select']); } } else if (!$USER->get('admin') && $results['data']) { foreach ($results['data'] as &$r) { if (!isset($r['email'])) { $r['email'] = '- ' . get_string('emailaddresshidden', 'admin') . ' -'; } } } $smarty = smarty_core(); $smarty->assign_by_ref('results', $results); $smarty->assign_by_ref('institutions', $institutions); $smarty->assign('USER', $USER); $smarty->assign('limit', $limit); $smarty->assign('limitoptions', array(10, 50, 100, 200, 500)); $smarty->assign('cols', $cols); $smarty->assign('ncols', count($cols)); $html = $smarty->fetch('searchresulttable.tpl'); return array($html, $cols, $pagination, array( 'url' => $searchurl, 'sortby' => $search->sortby, 'sortdir' => $search->sortdir )); } /** * Returns the search results for the export queue * * @param array $search The parameters we want to search against * @param int $offset What result to start showing paginated results from * @param int $limit How many results to show * * @return array A data structure containing results (see top of file). */ function build_admin_export_queue_results($search, $offset, $limit) { global $USER; $wantedparams = array('query', 'sortby', 'sortdir', 'institution'); $params = array(); foreach ($search as $k => $v) { if (!in_array($k, $wantedparams)) { continue; } if (!empty($v)) { $params[] = $k . '=' . $v; } } $searchurl = get_config('wwwroot') . 'admin/users/exportqueue.php?' . join('&', $params) . '&limit=' . $limit; // Use get_admin_user_search_results() as it hooks into the same // funky stuff the user search box query does on user/search.php page. $search->exportqueue = true; $results = get_admin_user_search_results($search, $offset, $limit); // Now that we have the users we need to match them up with their export_queue data if (!empty($results['count'])) { foreach ($results['data'] as $key => $data) { $used = array(); $exportdata = get_records_sql_assoc(' SELECT *, ' . db_format_tsfield('e.starttime', 'started') . ', ' . db_format_tsfield('e.ctime', 'added') . ' FROM {export_queue} e JOIN {export_queue_items} ei ON e.id = ei.exportqueueid AND e.usr = ? AND e.id = ? GROUP BY e.id, ei.id ORDER BY collection, view', array($data['id'], $data['eid'])); $exportdataall = false; if (empty($exportdata)) { // Try checking if it an 'all' export $exportdataall = get_record_sql("SELECT *, " . db_format_tsfield('starttime', 'started') . ", " . db_format_tsfield('ctime', 'added') . " FROM {export_queue} WHERE id = ? AND type = ?", array($data['eid'], 'all')); } if (empty($exportdataall) && empty($exportdata)) { // we have a problem with this row so will mark as failed $results['data'][$key]['status'] = get_string('exportfailed', 'admin', format_date($data['status'])); $results['data'][$key]['statustype'] = $statustype = 'failed'; continue; } // To get the main content title/url/type/id we look at the first row of the exportdata. if ($exportdataall) { $firstitem = $exportdataall; $contentdata = new stdClass(); $contentdata->title = get_string('allmydata', 'export'); $contentdata->type = 'all'; $results['data'][$key]['contentdata'] = $contentdata; } else { $firstitem = reset($exportdata); if (!empty($firstitem->type)) { $contentdata = new stdClass(); $contentdata->title = get_string('exporting' . $firstitem->type, 'export'); $contentdata->type = $firstitem->type; $results['data'][$key]['contentdata'] = $contentdata; } else { $results['data'][$key]['contentdata'] = get_export_contentdata($firstitem); } } // To get the status we check if the starttime is set if (empty($firstitem->starttime)) { $status = get_string('exportpending', 'admin', format_date($firstitem->added)); $statustype = 'pending'; } else if (!empty($firstitem->starttime)) { $status = get_string('exportfailed', 'admin', format_date($firstitem->started)); $statustype = 'failed'; } $results['data'][$key]['status'] = $status; $results['data'][$key]['statustype'] = $statustype; // Add on the raw exportdata allowing us to show the titles of all pages / artefacts // @todo allow all the titles to be displayed in an expanding box/area $results['data'][$key]['exportdata'] = $exportdata; } } $pagination = build_pagination(array( 'id' => 'admin_exportqueue_pagination', 'class' => 'center', 'url' => $searchurl, 'count' => $results['count'], 'setlimit' => true, 'limit' => $limit, 'jumplinks' => 8, 'numbersincludeprevnext' => 2, 'offset' => $offset, 'datatable' => 'searchresults', 'searchresultsheading' => 'resultsheading', 'jsonscript' => 'admin/users/exportqueue.json.php', )); $cols = array( 'icon' => array( 'template' => 'admin/users/searchiconcolumn.tpl', 'class' => 'center', 'accessible' => get_string('profileicon'), ), 'firstname' => array( 'name' => get_string('firstname'), 'sort' => true, 'template' => 'admin/users/searchfirstnamecolumn.tpl', ), 'lastname' => array( 'name' => get_string('lastname'), 'sort' => true, 'template' => 'admin/users/searchlastnamecolumn.tpl', ), 'preferredname' => array( 'name' => get_string('displayname'), 'sort' => true, ), 'username' => array( 'name' => get_string('username'), 'sort' => true, 'template' => 'admin/users/searchusernamecolumn.tpl', ), 'contentname' => array( 'name' => get_string('exportcontentname', 'admin'), 'sort' => false, 'template' => 'admin/users/searchexportcontentcolumn.tpl', ), 'status' => array( 'name' => get_string('status'), 'sort' => true, 'template' => 'admin/users/searchexportstatuscolumn.tpl', ), 'exportselect' => array( 'headhtml' => get_string('requeue', 'export') . '
' . get_string('All') . ' ' . get_string('none') . '', 'template' => 'admin/users/searchselectcolumnexport.tpl', 'class' => 'center nojs-hidden-table-cell', 'accessible' => get_string('bulkselect'), ), 'deleteselect' => array( 'headhtml' => get_string('delete') . '
' . get_string('All') . ' ' . get_string('none') . '', 'template' => 'admin/users/searchselectcolumnexportdelete.tpl', 'class' => 'center nojs-hidden-table-cell', 'accessible' => get_string('bulkselect'), ), ); $smarty = smarty_core(); $smarty->assign_by_ref('results', $results); $smarty->assign('USER', $USER); $smarty->assign('limit', $limit); $smarty->assign('limitoptions', array(10, 50, 100, 200, 500)); $smarty->assign('cols', $cols); $smarty->assign('ncols', count($cols)); $html = $smarty->fetch('searchresulttable.tpl'); if ($html != '') { $html .= $smarty->fetch('searchresulttablebuttons.tpl'); } return array($html, $cols, $pagination, array( 'url' => $searchurl, 'sortby' => $search->sortby, 'sortdir' => $search->sortdir )); } /** * Returns the search results for the archived submissions * * @param array $search The parameters we want to search against * @param int $offset What result to start showing paginated results from * @param int $limit How many results to show * * @return array A data structure containing results (see top of file). */ function build_admin_archived_submissions_results($search, $offset, $limit) { global $USER; $wantedparams = array('query', 'sortby', 'sortdir', 'institution'); $params = array(); foreach ($search as $k => $v) { if (!in_array($k, $wantedparams)) { continue; } if (!empty($v)) { $params[] = $k . '=' . $v; } } $searchurl = get_config('wwwroot') . 'admin/groups/archives.php?' . join('&', $params) . '&limit=' . $limit; // Use get_admin_user_search_results() as it hooks into the same // funky stuff the user search box query does on user/search.php page. $search->archivedsubmissions = true; $results = get_admin_user_search_results($search, $offset, $limit); // Now that we have the users we need to do some last minute alterations if (!empty($results['count'])) { foreach ($results['data'] as $key => $data) { // alter the archivectime to be human readable $results['data'][$key]['archivectime'] = format_date($data['archivectime']); // make sure the archive file is still on server at the path 'filepath' (not moved or deleted by server admin) $results['data'][$key]['filemissing'] = (!file_exists($data['filepath'] . $data['filename'])) ? true : false; // make the deleted group name more human readable $results['data'][$key]['groupdeleted'] = false; if (preg_match('/^(.*?)(\.deleted\.)(.*)$/', $data['submittedto'], $matches)) { $results['data'][$key]['groupdeleted'] = true; $results['data'][$key]['submittedto'] = $matches[1] . ' (' . get_string('deleted') . ' ' . format_date($matches[3]) . ')'; } } } $pagination = build_pagination(array( 'id' => 'admin_exportqueue_pagination', 'class' => 'center', 'url' => $searchurl, 'count' => $results['count'], 'setlimit' => true, 'limit' => $limit, 'jumplinks' => 8, 'numbersincludeprevnext' => 2, 'offset' => $offset, 'datatable' => 'searchresults', 'searchresultsheading' => 'resultsheading', 'jsonscript' => 'admin/groups/archives.json.php', )); $cols = array( 'submittedto' => array( 'name' => get_string('submittedto', 'admin'), 'sort' => true, 'template' => 'admin/groups/submittedtocontentcolumn.tpl', ), 'specialid' => array( 'name' => get_string('ID', 'admin'), 'sort' => true, ), 'icon' => array( 'template' => 'admin/users/searchiconcolumn.tpl', 'class' => 'center', 'accessible' => get_string('profileicon'), ), 'firstname' => array( 'name' => get_string('firstname'), 'sort' => true, 'template' => 'admin/users/searchfirstnamecolumn.tpl', ), 'lastname' => array( 'name' => get_string('lastname'), 'sort' => true, 'template' => 'admin/users/searchlastnamecolumn.tpl', ), 'preferredname' => array( 'name' => get_string('displayname'), 'sort' => true, ), 'username' => array( 'name' => get_string('username'), 'sort' => true, 'template' => 'admin/users/searchusernamecolumn.tpl', ), 'filetitle' => array( 'name' => get_string('filenameleap', 'admin'), 'sort' => true, 'template' => 'admin/groups/leap2acontentcolumn.tpl', ), 'archivectime' => array( 'name' => get_string('archivedon', 'admin'), 'sort' => true, ), ); $smarty = smarty_core(); $smarty->assign_by_ref('results', $results); $smarty->assign('USER', $USER); $smarty->assign('limit', $limit); $smarty->assign('limitoptions', array(10, 50, 100, 200, 500)); $smarty->assign('cols', $cols); $smarty->assign('ncols', count($cols)); $html = $smarty->fetch('searchresulttable.tpl'); return array($html, $cols, $pagination, array( 'url' => $searchurl, 'sortby' => $search->sortby, 'sortdir' => $search->sortdir )); } /** * Return the title, type and id of the item based on which is more important * * Takes an array containing ids on either or all of these items with ranking * preference in this order: * - collection * - view * and returns the title, type, and id of which ever one is present and is highest ranked * * @param array $item An array containing any or all of 'collection', 'view' ids * @return array The title/url/type/id information on the most senior one found. */ function get_export_contentdata($item) { // first make sure we have an array if (is_object($item)) { $item = (array)$item; } $record = new stdClass(); $record->title = ''; $record->url = null; $record->type = null; $record->id = 0; if (!empty($item['collection'])) { require_once('collection.php'); $collection = new Collection($item['collection']); $views = $collection->get('views'); $record->title = $collection->get('name'); $record->url = $views['views'][0]->fullurl; $record->type = 'collection'; $record->id = $item['collection']; } else if (!empty($item['view'])) { require_once('view.php'); $view = new View($item['view']); $record->title = $view->get('title'); $record->url = get_config('wwwroot') . 'view/view.php?id=' . $item['view']; $record->type = 'view'; $record->id = $item['view']; } return $record; } /** * Returns search results for users in a particular group * * The search term is applied against first and last names of the users in the group * * @param int $group The group to build results for * @param string $query A search string to filter by * @param int $offset What result to start showing paginated results from * @param int $limit How many results to show * @param array $membershiptype User membershiptype * @param bool $random Set to true if you want the result to be ordered by random, default false * @param int $friendof Only return friends of this user * */ function get_group_user_search_results($group, $query, $offset, $limit, $membershiptype, $order=null, $friendof=null, $sortoptionidx=null) { $plugin = get_config('searchplugin'); safe_require('search', $plugin); $searchclass = generate_class_name('search', $plugin); $constraints = array(); if (call_static_method($searchclass, 'can_process_raw_group_search_user_queries')) { // Pass the raw query string through to group_search_user; parsing of the // query depends on the plugin configuration. $queries = $query; } else { $queries = array(); if (!empty($query)) { list($words, $fullnames) = parse_name_query($query); foreach ($words as $word) { $queries[] = array( 'field' => 'firstname', 'type' => 'contains', 'string' => $word ); $queries[] = array( 'field' => 'lastname', 'type' => 'contains', 'string' => $word ); } foreach ($fullnames as $n) { $constraints[] = array( 'field' => 'firstname', 'type' => 'contains', 'string' => $n[0] ); $constraints[] = array( 'field' => 'lastname', 'type' => 'contains', 'string' => $n[1] ); } } } $results = call_static_method( $searchclass, 'group_search_user', $group, $queries, $constraints, $offset, $limit, $membershiptype, $order, $friendof, $sortoptionidx ); if ($results['count']) { $userids = array_map(create_function('$a', 'return $a["id"];'), $results['data']); $introductions = get_records_sql_assoc("SELECT \"owner\", title FROM {artefact} WHERE artefacttype = 'introduction' AND \"owner\" IN (" . implode(',', db_array_to_ph($userids)) . ')', $userids); foreach ($results['data'] as &$result) { $result['name'] = display_name($result); $result['introduction'] = isset($introductions[$result['id']]) ? $introductions[$result['id']]->title : ''; if (isset($result['jointime'])) { $result['jointime'] = format_date($result['jointime'], 'strftimedate'); } } } return $results; } /** * Given a query string and limits, return an array of matching groups using the * search plugin defined in config.php * * @param string The query string * @param integer How many results to return * @param integer What result to start at (0 == first result) * @return array A data structure containing results looking like ... * $results = array( * count => integer, // total number of results * limit => integer, // how many results are returned * offset => integer, // starting from which result * results => array( // the result records * array( * id => integer, * name => string, * owner => integer, * description => string, * ctime => string, * mtime => string, * ), * array( * id => integer, * name => string, * owner => integer, * description => string, * ctime => string, * mtime => string, * ), * array(...), * ), * ); */ function search_group($query_string, $limit, $offset = 0, $type = 'member', $groupcategory = '') { $plugin = get_config('searchplugin'); safe_require('search', $plugin); return call_static_method(generate_class_name('search', $plugin), 'search_group', $query_string, $limit, $offset, $type, $groupcategory); } function search_selfsearch($query_string, $limit, $offset, $type = 'all') { $plugin = get_config('searchplugin'); safe_require('search', $plugin); return call_static_method(generate_class_name('search', $plugin), 'self_search', $query_string, $limit, $offset, $type); } function get_portfolio_types_from_param($filter) { if (is_null($filter) || $filter == 'all') { return null; } if ($filter == 'view') { return array('view' => true, 'collection' => false, 'artefact' => false); } if ($filter == 'collection') { return array('view' => false, 'collection' => true, 'artefact' => false); } require_once(get_config('docroot') . 'artefact/lib.php'); return array('view' => false, 'collection' => false, 'artefact' => artefact_get_types_from_filter($filter)); } function get_portfolio_items_by_tag($tag, $owner, $limit, $offset, $sort='name', $type=null, $returntags=true) { // For now, can only be used to search a user's portfolio if (empty($owner->id) || empty($owner->type)) { throw new SystemException('get_views_and_artefacts_by_tag: invalid owner'); } if ($owner->type != 'user') { throw new SystemException('get_views_and_artefacts_by_tag only implemented for users'); } $types = get_portfolio_types_from_param($type); $plugin = 'internal'; safe_require('search', $plugin); $result = call_static_method(generate_class_name('search', $plugin), 'portfolio_search_by_tag', $tag, $owner, $limit, $offset, $sort, $types, $returntags); $result->filter = $result->type = $type ? $type : 'all'; return $result; } function get_search_plugins() { $searchpluginoptions = array(); if ($searchplugins = plugins_installed('search')) { foreach ($searchplugins as $plugin) { safe_require_plugin('search', $plugin->name, 'lib.php'); if (!call_static_method(generate_class_name('search', $plugin->name), 'is_available_for_site_setting')) { continue; } $searchpluginoptions[$plugin->name] = $plugin->name; $config_path = get_config('docroot') . 'search/' . $plugin->name . '/version.php'; if (is_readable($config_path)) { $config = new stdClass(); require_once($config_path); if (isset($config->name)) { $searchpluginoptions[$plugin->name] = $config->name; } } } } return $searchpluginoptions; } /** * Given a filter string and limits, return an array of matching friends. * * @param string The filter string * @param integer How many results to return * @param integer What result to start at (0 == first result) * @return array A data structure containing results looking like ... * $results = array( * count => integer, // total number of results * limit => integer, // how many results are returned * offset => integer, // starting from which result * results => array( // the result records * array( * id => integer, //user id * ), * array(...), * ), * ); */ function search_friend($filter, $limit, $offset) { global $USER; $userid = $USER->get('id'); if (!in_array($filter, array('all','current','pending'))) { throw new SystemException('Invalid search filter'); } $sql = array(); $count = 0; if (in_array($filter, array('all', 'current'))) { $count += count_records_sql('SELECT COUNT(usr1) FROM {usr_friend} JOIN {usr} u1 ON (u1.id = usr1 AND u1.deleted = 0) JOIN {usr} u2 ON (u2.id = usr2 AND u2.deleted = 0) WHERE usr1 = ? OR usr2 = ?', array($userid, $userid) ); array_push($sql, 'SELECT usr2 AS id, 2 AS status FROM {usr_friend} WHERE usr1 = ? '); array_push($sql, 'SELECT usr1 AS id, 2 AS status FROM {usr_friend} WHERE usr2 = ? '); } if (in_array($filter, array('all', 'pending'))) { $count += count_records_sql('SELECT COUNT("owner") FROM {usr_friend_request} JOIN {usr} u ON (u.id = requester AND u.deleted = 0) WHERE "owner" = ?', array($userid) ); array_push($sql, 'SELECT requester AS id, 1 AS status FROM {usr_friend_request} WHERE "owner" = ? '); } $data = get_column_sql('SELECT f.id FROM (' . join('UNION ', $sql) . ') f JOIN {usr} u ON (f.id = u.id AND u.deleted = 0) ORDER BY status, firstname, lastname, u.id LIMIT ? OFFSET ?', array_merge(array_pad($values=array(), count($sql), $userid), array($limit, $offset))); foreach ($data as &$result) { $result = array('id' => $result); } return array( 'count' => $count, 'limit' => $limit, 'offset' => $offset, 'data' => $data, ); }