public function getSubscribers($catid, $topic, $subscriptions = false, $moderators = false, $admins = false, $excludeList = null) { $topic = KunenaForumTopicHelper::get($topic); if (!$topic->exists()) return array(); if ($subscriptions) { $subslist = $this->loadSubscribers($topic, (int)$subscriptions); } if ($moderators) { $modlist = array(); if (!empty(self::$moderatorsByCatid[0])) $modlist += self::$moderatorsByCatid[0]; if (!empty(self::$moderatorsByCatid[$catid])) $modlist += self::$moderatorsByCatid[$catid]; // If category has no moderators, send email to admins instead if (empty($modlist)) $admins = true; } if ($admins) { $adminlist = array(); if (!empty(self::$adminsByCatid[0])) $adminlist += self::$adminsByCatid[0]; if (!empty(self::$adminsByCatid[$catid])) $adminlist += self::$adminsByCatid[$catid]; } $query = new KunenaDatabaseQuery(); $query->select('u.id, u.name, u.username, u.email'); $query->from('#__users AS u'); $query->where("u.block=0"); $userlist = array(); if (!empty($subslist)) { $userlist = $subslist; $subslist = implode(',', array_keys($subslist)); $query->select("IF( u.id IN ({$subslist}), 1, 0 ) AS subscription"); } else { $query->select("0 AS subscription"); } if (!empty($modlist)) { $userlist += $modlist; $modlist = implode(',', array_keys($modlist)); $query->select("IF( u.id IN ({$modlist}), 1, 0 ) AS moderator"); } else { $query->select("0 AS moderator"); } if (!empty($adminlist)) { $userlist += $adminlist; $adminlist = implode(',', array_keys($adminlist)); $query->select("IF( u.id IN ({$adminlist}), 1, 0 ) AS admin"); } else { $query->select("0 AS admin"); } if (empty($excludeList)) { // false, null, '', 0 and array(): get all subscribers $excludeList = array(); } elseif (is_array($excludeList)) { // array() needs to be flipped to get userids into keys $excludeList = array_flip($excludeList); } else { // Others: let's assume that we have comma separated list of values (string) $excludeList = array_flip(explode(',', (string) $excludeList)); } $userlist = array_diff_key($userlist, $excludeList); $userids = array(); if (!empty($userlist)) { $userlist = implode(',', array_keys($userlist)); $query->where("u.id IN ({$userlist})"); $db = JFactory::getDBO(); $db->setQuery ( $query ); $userids = (array) $db->loadObjectList (); KunenaError::checkDatabaseError(); } return $userids; }
/** * Move topic or parts of it into another category or topic. * * @param object $target Target KunenaForumCategory or KunenaForumTopic * @param mixed $ids false, array of message Ids or JDate * @param bool $shadow Leave visible shadow topic. * @param string $subject New subject * @param bool $subjectall Change subject from every message * @param int $topic_iconid Define a new topic icon * * @return bool|KunenaForumCategory|KunenaForumTopic Target KunenaForumCategory or KunenaForumTopic or false on failure */ public function move($target, $ids = false, $shadow = false, $subject = '', $subjectall = false, $topic_iconid = null) { // Warning: logic in this function is very complicated and even with full understanding its easy to miss some details! // Clear authentication cache $this->_authfcache = $this->_authccache = $this->_authcache = array(); // Cleanup input if (!$ids instanceof JDate) { if (!is_array($ids)) { $ids = explode(',', (string) $ids); } $mesids = array(); foreach ($ids as $id) { $mesids[(int) $id] = (int) $id; } unset($mesids[0]); $ids = implode(',', $mesids); } $subject = (string) $subject; // First we need to check if there will be messages left in the old topic if ($ids) { $query = new KunenaDatabaseQuery(); $query->select('COUNT(*)')->from('#__kunena_messages')->where("thread={$this->id}"); if ($ids instanceof JDate) { // All older messages will remain (including unapproved, deleted) $query->where("time<{$ids->toUnix()}"); } else { // All messages that were not selected will remain $query->where("id NOT IN ({$ids})"); } $this->_db->setQuery($query); $oldcount = (int) $this->_db->loadResult(); if ($this->_db->getErrorNum()) { $this->setError($this->_db->getError()); return false; } // So are we moving the whole topic? if (!$oldcount) { $ids = ''; } } $categoryFrom = $this->getCategory(); // Find out where we are moving the messages if (!$target || !$target->exists()) { $this->setError(JText::printf('COM_KUNENA_MODERATION_ERROR_NO_TARGET', $this->id)); return false; } elseif ($target instanceof KunenaForumTopic) { // Move messages into another topic (original topic will always remain, either as real one or shadow) if ($target == $this) { // We cannot move topic into itself $this->setError(JText::sprintf('COM_KUNENA_MODERATION_ERROR_SAME_TARGET_THREAD', $this->id, $this->id)); return false; } if ($this->moved_id) { // Moved topic cannot be merged with another topic -- it has no posts to be moved $this->setError(JText::sprintf('COM_KUNENA_MODERATION_ERROR_ALREADY_SHADOW', $this->id)); return false; } if ($this->poll_id && $target->poll_id) { // We cannot currently have 2 polls in one topic -- fail $this->setError(JText::_('COM_KUNENA_MODERATION_CANNOT_MOVE_TOPIC_WITH_POLL_INTO_ANOTHER_WITH_POLL')); return false; } if ($subjectall) { $subject = $target->subject; } } elseif ($target instanceof KunenaForumCategory) { // Move messages into category if ($target->isSection()) { // Section cannot have any topics $this->setError(JText::_('COM_KUNENA_MODERATION_ERROR_NOT_MOVE_SECTION')); return false; } // Save category information for later use $categoryTarget = $target; if ($this->moved_id) { // Move shadow topic and we are done $this->category_id = $categoryTarget->id; if ($subject) { $this->subject = $subject; } $this->save(false); return $target; } if ($shadow || $ids) { // Create new topic for the moved messages $target = clone $this; $target->exists(false); $target->id = 0; $target->hits = 0; $target->params = ''; } else { // If we just move into another category, we can keep using the old topic $target = $this; } // Did user want to change the subject? if ($subject) { $target->subject = $subject; } // Did user want to change the topic icon? if (!is_null($topic_iconid)) { $target->icon_id = $topic_iconid; } // Did user want to change category? $target->category_id = $categoryTarget->id; } else { $this->setError(JText::_('COM_KUNENA_MODERATION_ERROR_WRONG_TARGET')); return false; } // For now on we assume that at least one message will be moved (=authorization check was called on topic/message) // We will soon need target topic id, so save if it doesn't exist if (!$target->exists()) { if (!$target->save(false)) { $this->setError($target->getError()); return false; } } // Move messages (set new category and topic) $query = new KunenaDatabaseQuery(); $query->update('#__kunena_messages')->set("catid={$target->category_id}")->set("thread={$target->id}")->where("thread={$this->id}"); // Did we want to change subject from all the messages? if ($subjectall && !empty($subject)) { $query->set("subject={$this->_db->quote($subject)}"); } if ($ids instanceof JDate) { // Move all newer messages (includes unapproved, deleted messages) $query->where("time>={$ids->toUnix()}"); } elseif ($ids) { // Move individual messages $query->where("id IN ({$ids})"); } $this->_db->setQuery($query); $this->_db->query(); if ($this->_db->getErrorNum()) { $this->setError($this->_db->getError()); return false; } // Make sure that all messages in topic have unique time (deterministic without ORDER BY time, id) $query = "SET @ktime:=0"; $this->_db->setQuery($query); $this->_db->query(); if ($this->_db->getErrorNum()) { $this->setError($this->_db->getError()); return false; } $query = "UPDATE #__kunena_messages SET time=IF(time<=@ktime,@ktime:=@ktime+1,@ktime:=time) WHERE thread={$target->id} ORDER BY time ASC, id ASC"; $this->_db->setQuery($query); $this->_db->query(); if ($this->_db->getErrorNum()) { $this->setError($this->_db->getError()); return false; } // If all messages were moved into another topic, we need to move poll as well if ($this->poll_id && !$ids && $target != $this) { // Note: We may already have saved cloned target (having poll_id already in there) $target->poll_id = $this->poll_id; // Note: Do not remove poll from shadow: information could still be used to show icon etc $query = "UPDATE #__kunena_polls SET `threadid`={$this->_db->Quote($target->id)} WHERE `threadid`={$this->_db->Quote($this->id)}"; $this->_db->setQuery($query); $this->_db->query(); if ($this->_db->getErrorNum()) { $this->setError($this->_db->getError()); return false; } } // When moving only first message keep poll only on target topic if ($this->poll_id && $target != $this && $ids) { if ($ids && $this->first_post_id) { $this->poll_id = 0; } } if (!$ids && $target != $this) { // Leave shadow from old topic $this->moved_id = $target->id; if (!$shadow) { // Mark shadow topic as deleted $this->hold = 2; } } // Note: We already saved possible target earlier, now save only $this if (!$this->save(false)) { return false; } if (!$ids && !empty($categoryTarget)) { // Move topic into another category // Update user topic information (topic, category) KunenaForumTopicUserHelper::move($this, $target); // TODO: do we need this? //KunenaForumTopicUserReadHelper::move($this, $target); // Remove topic and posts from the old category $categoryFrom->update($this, -1, -$this->posts); // Add topic and posts into the new category $categoryTarget->update($target, 1, $this->posts); } elseif (!$ids) { // Moving topic into another topic // Add new posts, hits and attachments into the target topic $target->posts += $this->posts; $target->hits += $this->hits; $target->attachments += $this->attachments; // Update first and last post information into the target topic $target->updatePostInfo($this->first_post_id, $this->first_post_time, $this->first_post_userid, $this->first_post_message, $this->first_post_guest_name); $target->updatePostInfo($this->last_post_id, $this->last_post_time, $this->last_post_userid, $this->last_post_message, $this->last_post_guest_name); // Save target topic if (!$target->save(false)) { $this->setError($target->getError()); return false; } // Update user topic information (topic, category) KunenaForumTopicUserHelper::merge($this, $target); // TODO: do we need this? //KunenaForumTopicUserReadHelper::merge($this, $target); // Remove topic and posts from the old category $this->getCategory()->update($this, -1, -$this->posts); // Add posts into the new category $target->getCategory()->update($target, 0, $this->posts); } else { // Both topics have changed and we have no idea how much: force full recount // TODO: we can do this faster.. $this->recount(); $target->recount(); } return $target; }
/** * JXtended: Grabs all groups mapped to an ARO. * * A root group value can be specified for looking at sub-tree * (results include the root group) * * @param string The section value or the ARO or AXO * @param string The value of the ARO or AXO * @param integer The value of the group to start at (optional) * @param string The type of group, either ARO or AXO (optional) */ protected function acl_get_groups($sectionValue, $value, $rootGroupValue=NULL, $type='ARO') { static $cache = null; $db = JFactory::getDbo(); $type = strtolower($type); if ($type != 'aro' && $type != 'axo') { return array(); } if (($sectionValue === '' || $sectionValue === null) && ($value === '' || $value === null)) { return array(); } // Simple cache if ($cache === null) { $cache = array(); } // Generate unique cache id. $cacheId = 'acl_get_groups_'.$sectionValue.'-'.$value.'-'.$rootGroupValue.'-'.$type; if (!isset($cache[$cacheId])) { $query = new KunenaDatabaseQuery(); // Make sure we get the groups $query->select('DISTINCT g2.id'); $query->from('#__core_acl_'.$type.' AS o'); $query->join('INNER', '#__core_acl_groups_'.$type.'_map AS gm ON gm.'. $type .'_id=o.id'); $query->join('INNER', '#__core_acl_'.$type.'_groups AS g1 ON g1.id = gm.group_id'); $query->where('(o.section_value='. $db->quote($sectionValue) .' AND o.value='. $db->quote($value) .')'); /* * If root group value is specified, we have to narrow this query down * to just groups deeper in the tree then what is specified. * This essentially creates a virtual "subtree" and ignores all outside groups. * Useful for sites like sourceforge where you may seperate groups by "project". */ if ( $rootGroupValue != '') { $query->join('INNER', '#__core_acl_'.$type.'_groups AS g3 ON g3.value='. $db->quote($rootGroupValue)); $query->join('INNER', '#__core_acl_'.$type.'_groups AS g2 ON ((g2.lft BETWEEN g3.lft AND g1.lft) AND (g2.rgt BETWEEN g1.rgt AND g3.rgt))'); } else { $query->join('INNER', '#__core_acl_'.$type.'_groups AS g2 ON (g2.lft <= g1.lft AND g2.rgt >= g1.rgt)'); } $db->setQuery($query); $cache[$cacheId] = $db->loadResultArray(); } return $cache[$cacheId]; }
/** * @param int $catid * @param mixed $topic * @param mixed $type * @param bool $moderators * @param bool $admins * @param mixed $excludeList * * @return array */ public function getSubscribers($catid, $topic, $type = false, $moderators = false, $admins = false, $excludeList = null) { $topic = KunenaForumTopicHelper::get($topic); $category = $topic->getCategory(); if (!$topic->exists()) { return array(); } $modlist = array(); if (!empty($this->moderatorsByCatid[0])) { $modlist += $this->moderatorsByCatid[0]; } if (!empty($this->moderatorsByCatid[$catid])) { $modlist += $this->moderatorsByCatid[$catid]; } $adminlist = array(); if (!empty($this->adminsByCatid[0])) { $adminlist += $this->adminsByCatid[0]; } if (!empty($this->adminsByCatid[$catid])) { $adminlist += $this->adminsByCatid[$catid]; } if ($type) { $subscribers = $this->loadSubscribers($topic, $type); $allow = $deny = array(); if (!empty($subscribers)) { /** @var KunenaAccess $access */ foreach ($this->accesstypes[$category->accesstype] as $access) { if (method_exists($access, 'authoriseUsers')) { list($a, $d) = $access->authoriseUsers($topic, $subscribers); if (!empty($a)) { $allow += array_combine($a, $a); } if (!empty($d)) { $deny += array_combine($d, $d); } } } } $subslist = array_diff($allow, $deny); // Category administrators and moderators override ACL $subslist += array_intersect_key($adminlist, array_flip($subscribers)); $subslist += array_intersect_key($modlist, array_flip($subscribers)); } if (!$moderators) { $modlist = array(); } else { // If category has no moderators, send email to admins instead if (empty($modlist)) { $admins = true; } } if (!$admins) { $adminlist = array(); } $query = new KunenaDatabaseQuery(); $query->select('u.id, u.name, u.username, u.email'); $query->from('#__users AS u'); $query->where("u.block=0"); $userlist = array(); if (!empty($subslist)) { $userlist += $subslist; $subslist = implode(',', array_keys($subslist)); $query->select("IF( u.id IN ({$subslist}), 1, 0 ) AS subscription"); } else { $query->select("0 AS subscription"); } if (!empty($modlist)) { $userlist += $modlist; $modlist = implode(',', array_keys($modlist)); $query->select("IF( u.id IN ({$modlist}), 1, 0 ) AS moderator"); } else { $query->select("0 AS moderator"); } if (!empty($adminlist)) { $userlist += $adminlist; $adminlist = implode(',', array_keys($adminlist)); $query->select("IF( u.id IN ({$adminlist}), 1, 0 ) AS admin"); } else { $query->select("0 AS admin"); } if (empty($excludeList)) { // false, null, '', 0 and array(): get all subscribers $excludeList = array(); } elseif (is_array($excludeList)) { // array() needs to be flipped to get userids into keys $excludeList = array_flip($excludeList); } else { // Others: let's assume that we have comma separated list of values (string) $excludeList = array_flip(explode(',', (string) $excludeList)); } $userlist = array_diff_key($userlist, $excludeList); $userids = array(); if (!empty($userlist)) { $userlist = implode(',', array_keys($userlist)); $query->where("u.id IN ({$userlist})"); $db = JFactory::getDBO(); $db->setQuery($query); $userids = (array) $db->loadObjectList(); KunenaError::checkDatabaseError(); } return $userids; }
protected function _get_user_groups($userid) { static $cache = array(); $userid = intval($userid); if (!$userid) { return array(29); } if (!isset($cache[$userid])) { $db = JFactory::getDbo(); $query = new KunenaDatabaseQuery(); $query->select('g.id'); $query->from('#__core_acl_aro AS o'); $query->join('INNER', '#__core_acl_groups_aro_map AS gm ON gm.aro_id=o.id'); $query->join('INNER', '#__core_acl_aro_groups AS g ON g.id = gm.group_id'); $query->where("(o.section_value='users' AND o.value=" . $db->quote($userid) . ')'); $db->setQuery($query); $cache[$userid] = $db->loadResultArray(); } return $cache[$userid]; }
static public function getLatestMessages($categories=false, $limitstart=0, $limit=0, $params=array()) { $reverse = isset($params['reverse']) ? (int) $params['reverse'] : 0; $orderby = isset($params['orderby']) ? (string) $params['orderby'] : 'm.time DESC'; $starttime = isset($params['starttime']) ? (int) $params['starttime'] : 0; $mode = isset($params['mode']) ? $params['mode'] : 'recent'; $user = isset($params['user']) ? $params['user'] : false; $where = isset($params['where']) ? (string) $params['where'] : ''; $childforums = isset($params['childforums']) ? (bool) $params['childforums'] : false; $db = JFactory::getDBO(); // FIXME: use right config setting if ($limit < 1) $limit = KunenaFactory::getConfig ()->threads_per_page; $cquery = new KunenaDatabaseQuery(); $cquery->select('COUNT(*)') ->from('#__kunena_messages AS m') ->innerJoin('#__kunena_messages_text AS t ON m.id = t.mesid') ->where('m.moved=0'); // TODO: remove column $rquery = new KunenaDatabaseQuery(); $rquery->select('m.*, t.message') ->from('#__kunena_messages AS m') ->innerJoin('#__kunena_messages_text AS t ON m.id = t.mesid') ->where('m.moved=0') // TODO: remove column ->order($orderby); $authorise = 'read'; $hold = 'm.hold=0'; $userfield = 'm.userid'; switch ($mode) { case 'unapproved': $authorise = 'approve'; $hold = "m.hold=1"; break; case 'deleted': $authorise = 'undelete'; $hold = "m.hold>=2"; break; case 'mythanks': $userfield = 'th.userid'; $cquery->innerJoin('#__kunena_thankyou AS th ON m.id = th.postid'); $rquery->innerJoin('#__kunena_thankyou AS th ON m.id = th.postid'); break; case 'thankyou': $userfield = 'th.targetuserid'; $cquery->innerJoin('#__kunena_thankyou AS th ON m.id = th.postid'); $rquery->innerJoin('#__kunena_thankyou AS th ON m.id = th.postid'); break; case 'recent': default: } if (is_array($categories) && in_array(0, $categories)) { $categories = false; } $categories = KunenaForumCategoryHelper::getCategories($categories, $reverse, 'topic.'.$authorise); if ($childforums) { $categories += KunenaForumCategoryHelper::getChildren($categories, -1, false, array('action'=>'topic.'.$authorise)); } $catlist = array(); foreach ($categories as $category) { $catlist += $category->getChannels(); } if (empty($catlist)) return array(0, array()); $allowed = implode(',', array_keys($catlist)); $cquery->where("m.catid IN ({$allowed})"); $rquery->where("m.catid IN ({$allowed})"); $cquery->where($hold); $rquery->where($hold); if ($user) { $cquery->where("{$userfield}={$db->Quote($user)}"); $rquery->where("{$userfield}={$db->Quote($user)}"); } // Negative time means no time if ($starttime == 0) { $starttime = KunenaFactory::getSession ()->lasttime; } elseif ($starttime > 0) { $starttime = JFactory::getDate ()->toUnix () - ($starttime * 3600); } if ($starttime > 0) { $cquery->where("m.time>{$db->Quote($starttime)}"); $rquery->where("m.time>{$db->Quote($starttime)}"); } if ($where) { $cquery->where($where); $rquery->where($where); } $db->setQuery ( $cquery ); $total = ( int ) $db->loadResult (); if (KunenaError::checkDatabaseError() || !$total) return array(0, array()); // If out of range, use last page if ($total < $limitstart) $limitstart = intval($total / $limit) * $limit; $db->setQuery ( $rquery, $limitstart, $limit ); $results = $db->loadObjectList (); if (KunenaError::checkDatabaseError()) return array(0, array()); $messages = array(); foreach ( $results as $result ) { $instance = new KunenaForumMessage (false); $instance->setProperties ( $result ); $instance->exists(true); self::$_instances [$instance->id] = $instance; $messages[$instance->id] = $instance; } unset ($results); return array($total, $messages); }
/** * Method to delete a row from the database table by primary key value. * * @param mixed $keys An optional primary key value to delete. If not set the * instance property value is used. * * @return boolean True on success. * * @link http://docs.joomla.org/JTable/delete * @since Joomla 11.1 */ public function delete($keys = null) { // Initialise variables. if (empty($keys)) { // If empty, use the value of the current key if (!is_array($this->_tbl_key)) { $keyName = $this->_tbl_key; $keyValue = $this->$keyName; // If null primary key there's is no need to delete if(is_null($keyValue)) { $e = new JException(JText::_('JLIB_DATABASE_ERROR_NULL_PRIMARY_KEY')); $this->setError($e); return false; } $keys = array($keyName => $keyValue); } else { $keys = array(); foreach ($this->_tbl_key as $keyName) { $keyValue = $this->$keyName; $keys[$keyName] = $keyValue; // If null primary key there's is no need to delete if(is_null($keyValue)) { $e = new JException(JText::_('JLIB_DATABASE_ERROR_NULL_PRIMARY_KEY')); $this->setError($e); return false; } } } } elseif (!is_array($keys)) { // Delete by primary key. $keys = array($this->_tbl_key => $keys); } // Delete the row by primary key. $query = new KunenaDatabaseQuery(); $query->delete(); $query->from($this->_tbl); foreach ($keys as $key=>$value) { $query->where("{$this->_db->nameQuote($key)} = {$this->_db->quote($value)}"); } $this->_db->setQuery($query); // Check for a database error. if (!$this->_db->query()) { $e = new JException(JText::sprintf('JLIB_DATABASE_ERROR_DELETE_FAILED', get_class($this), $this->_db->getErrorMsg())); $this->setError($e); return false; } return true; }
public function load($keys = null, $reset = true) { if (empty($keys)) { // If empty, use the value of the current key if (!is_array($this->_tbl_key)) { $keyName = $this->_tbl_key; $keyValue = $this->$keyName; // If empty primary key there's is no need to load anything if(empty($keyValue)) return false; $keys = array($keyName => $keyValue); } else { $keys = array(); foreach ($this->_tbl_key as $keyName) { $keyValue = $this->$keyName; $keys[$keyName] = $keyValue; // If null primary key there's is no need to load anything if($keyValue === null) return false; } } } elseif (!is_array($keys)) { // Load by primary key. $keys = array($keys); } if ($reset) $this->reset(); // Initialise the query. $query = new KunenaDatabaseQuery(); $query->select('*'); $query->from($this->_tbl); $fields = array_keys($this->getProperties()); if (is_array($this->_tbl_key)) reset($this->_tbl_key); foreach ($keys as $field => $value) { if (is_numeric($field)) { if (!is_array($this->_tbl_key)) { $field = $this->_tbl_key; } else { list($i,$field) = each($this->_tbl_key); } $this->$field = $value; } // Check that $field is in the table. if (!in_array($field, $fields)) { $e = new JException(JText::sprintf('JLIB_DATABASE_ERROR_CLASS_IS_MISSING_FIELD', get_class($this), $field)); $this->setError($e); return false; } // Add the search tuple to the query. $query->where($this->_db->nameQuote($field).' = '.$this->_db->quote($value)); } $this->_db->setQuery($query); $row = $this->_db->loadAssoc(); // Check for a database error. if ($this->_db->getErrorNum()) { $e = new JException($this->_db->getErrorMsg()); $this->setError($e); return false; } // Check that we have a result. if (empty($row)) { $e = new JException(JText::_('JLIB_DATABASE_ERROR_EMPTY_ROW_RETURNED')); $this->setError($e); return false; } // Bind the object with the row and return. return $this->_exists = $this->bind($row); }
protected function checkSubscribers($category, &$userids) { $userlist = implode(',', $userids); $db = JFactory::getDBO(); $query = new KunenaDatabaseQuery(); $query->select('u.id'); $query->from('#__users AS u'); $query->where("u.block=0"); $query->where("u.id IN ({$userlist})"); if ($category->accesstype == 'joomla') { // Check against Joomla access level if ($category->access > 1) { // Special users = not in registered group $query->where("u.gid!=18"); } } elseif ($category->accesstype == 'none') { // Check against Joomla user groups $public = $this->_get_groups($category->pub_access, $category->pub_recurse); $admin = $category->pub_access > 0 ? $this->_get_groups($category->admin_access, $category->admin_recurse) : array(); $groups = implode(',', array_unique(array_merge($public, $admin))); if ($groups) { $query->join('LEFT', "#__noixacl_multigroups AS g ON g.id_user=u.id"); $query->where("(u.gid IN ({$groups}) OR g.id_group IN ({$groups}))"); } } else { return array(); } $db->setQuery($query); $userids = (array) $db->loadResultArray(); KunenaError::checkDatabaseError(); }