/** * * @desc This function performs a generic search * against the database. Originaly from the mambot * but enhanced for wider searches * @param array $ of arrays $searchArray The lists of what to search for * i.e.: array( array( 'phrase'=>'search phrases', mode=>'exact'), * array( 'phrase=>'..... * Currently only uses the FIRST array request. (FUTURE: multiples) * @param string $ The ordering of the results (newest...etc). * Prefix with a '-' to reverse the ordering. * @param int $ the categories to search for (0=all) * @param mixed $ Either an array of terms to return or '*' * (Array is 'column-name' => 'return name'.) * @param array $ List of options for searching * * NOTE: We are NOT assured that we have $_DOCMAN and all the other goodies. * (we may be just from mambot) */ function search(&$searchArray, $ordering = '', $cats = '', $columns = '', $options = array()) { global $database, $my, $_DOCMAN; $_DMUSER = $_DOCMAN->getUser(); $searchterms = array_pop($searchArray); // Only do one (for now) if (empty($options)) { $options = array('search_name', 'search_description'); } if ($ordering == '') { $ordering = 'newest'; } $registered = $_DOCMAN->getCfg('registered'); $perpage = $_DOCMAN->getCfg('perpage'); $authorCan = $_DOCMAN->getCfg('author_can', '9999'); $userid = intval($my->id); // Guests who can browse can also search for documents //if (! $registered > 0) { // return array(); //} // Fetch 'acl' stuff. (Switch to class later?) /* $specials = array('super administrator', 'manager', 'administrator'); $specialcompat = $_DOCMAN->getCfg('specialcompat', _DM_SPECIALCOMPAT_DM13); if($specialcompat == _DM_SPECIALCOMPAT_J10) { $specials[] = 'author'; $specials[] = 'editor'; $specials[] = 'publisher'; } $isAdmin = (in_array( strtolower($my->usertype), $specials)); */ $isAdmin = $_DMUSER->isAdmin; // ------------------------------------- // Fetch the search options. Passed in options array // ------------------------------------- $search_col = array(); if (is_array($options)) { if (in_array('search_name', $options)) { $search_col[] = 'DM.dmname '; } if (in_array('search_description', $options) || in_array('search_desc', $options)) { $search_col[] = 'DM.dmdescription '; } if (in_array('search_cat', $options)) { $search_col[] = "CAT.title "; $search_col[] = "CAT.name "; $search_col[] = "SUB.title "; $search_col[] = "SUB.name "; } } if (count($search_col) == 0) { return array(); // Have to search SOMETHING! } // BUILD QUERY PARTS $search_mode = $searchterms['search_mode']; $text = trim($searchterms['search_phrase']); // fix for http://joomlacode.org/gf/project/docman/tracker/?action=TrackerItemEdit&tracker_item_id=7999 $text = htmlentities($text, ENT_QUOTES); if (!$text) { return array(); } // (1) Format search 'phrase' into SQL $invert = false; if (substr($search_mode, 0, 1) == '-') { $invert = true; $search_mode = substr($search_mode, 1); } $wheres = array(); switch ($search_mode) { case 'exact': foreach ($search_col as $col) { $wheres[] = $col . "LIKE '%{$text}%'"; } $where = '(' . implode(') OR (', $wheres) . ')'; break; case 'any': // Fall through for regex $text = implode('|', explode(' ', $text)); case 'regex': foreach ($search_col as $col) { $wheres[] = $col . "RLIKE '{$text}'"; } $where = '(' . implode(' OR ', $wheres) . ')'; break; case 'all': default: $words = explode(' ', $text); foreach ($search_col as $col) { $wheres2 = array(); foreach ($words as $word) { $wheres2[] = $col . "LIKE '%{$word}%'"; } $wheres[] = implode(' AND ', $wheres2); } $where = '(' . implode(') OR (', $wheres) . ')'; break; } if ($invert) { $where = 'NOT ( ' . $where . ')'; } // DEBUG: // echo "<pre>WHERE is: $where</pre>"; // (2) Create the 'ORDER BY' section based on user request $_DM_SEARCH_SORT_ORDER = array('newest' => 'DM.dmlastupdateon DDD', 'oldest' => 'DM.dmlastupdateon AAA', 'popular' => 'DM.dmcounter DDD', 'alpha' => 'DM.dmname AAA', 'category' => 'CAT.title AAA, SUB.title AAA, DM.dmname AAA'); $_DM_SEARCH_PATTERN = array('/DDD/', '/AAA/'); $invert = false; if (substr($ordering, 0, 1) == '-') { $ordering = substr($ordering, 1); $invert = true; } $order = $_DM_SEARCH_SORT_ORDER[$ordering]; if ($invert) { $order = preg_replace($_DM_SEARCH_PATTERN, array('ASC', 'DESC'), $order); } else { $order = preg_replace($_DM_SEARCH_PATTERN, array('DESC', 'ASC'), $order); } // (3) SQL WHERE portion based on user access priviledges if ($isAdmin) { $user_filter = " (SUB.access=" . _DM_ACCESS_PUBLIC . " OR SUB.access=" . _DM_ACCESS_REGISTERED . ")"; } else { if ($userid > 0) { // Logged IN $user_groups = DOCMAN_Docs::_dmCheckGroupsUserIn(); $user_filter = "(" . "\n DM.dmowner=" . _DM_PERMIT_EVERYONE . "\n OR DM.dmowner=" . _DM_PERMIT_REGISTERED . "\n OR DM.dmowner=" . $userid . "\n OR DM.dmowner IN ({$user_groups}) " . "\n OR DM.dmmantainedby=" . $userid . "\n OR DM.dmmantainedby IN ({$user_groups}) "; if ($authorCan > 0) { $user_filter .= "\n OR DM.dmsubmitedby = {$userid}"; } $user_filter .= ")" . "\n AND (SUB.access=" . _DM_ACCESS_PUBLIC . "\n OR SUB.access=" . _DM_ACCESS_REGISTERED . ")"; } else { // NOT logged in $user_filter = " DM.dmowner=" . _DM_PERMIT_EVERYONE . "\n AND SUB.access=" . _DM_ACCESS_PUBLIC; } // endif $userid } // endif isAdmin // (4)Build up the category list (if they selected it) if ($cats != '' && $cats != 0) { $user_filter .= "\n AND DM.catid "; if (is_array($cats)) { $user_filter .= 'IN (' . implode(',', $cats) . ')'; } else { $user_filter .= "= {$cats}"; } } // (5) Build up list of columns to return if (is_array($columns)) { foreach ($columns as $key => $value) { $list[] = "\n\t{$key} AS {$value}"; } $list_terms = implode(',', $list); } else { if ($columns != '' && $columns != '*') { $list_terms = $columns; } else { $list_terms = 'DM.* , DM.catid AS docman_catid'; } } // (*) Build final query for SQL lookup $query = "SELECT {$list_terms} " . "\nFROM #__docman AS DM " . "\nLEFT JOIN #__categories AS SUB ON SUB.id = DM.catid" . "\nLEFT JOIN #__categories AS CAT ON CAT.id = SUB.parent_id" . "\nWHERE {$user_filter} " . "\n AND DM.published=1 AND DM.approved=1" . "\n AND ({$where}) " . "\nORDER BY {$order}"; // TODO: add proper pagination instead of hardcoded limit? $database->setQuery($query, 0, 20); $rows = $database->loadObjectList(); $cache = array(); // Fill in the correct sections for ($r = 0; $r < count($rows); $r++) { $rows[$r]->section = @$options['section_prefix'] . DOCMAN_Docs::_dmSearchSection($rows[$r]->catid, $cache, '/') . @$options['section_suffix']; } // FINAL SORT: // We couldn't sort by category until now (we didn't HAVE a category) if ($order == 'category') { if ($invert) { usort($rows, create_function("{$a},{$b}", "return strcasecmp({$a->section} . {$a->dmname} , {$b->section} . {$b->dmname});")); } else { usort($rows, create_function("{$a},{$b}", "return strcasecmp({$b->section} . {$b->dmname} , {$a->section} . {$a->dmname});")); } } return $rows; }