Ejemplo n.º 1
0
 /**
  * Returns group members
  *
  * @return {Integer[]}	Array of userIDs
  */
 public function getMembers()
 {
     if (!$this->exists()) {
         return array();
     }
     $sql = "SELECT userID FROM groupUsers WHERE groupID=? AND role='member'";
     $ids = Zotero_DB::columnQuery($sql, $this->id);
     if (!$ids) {
         return array();
     }
     $ids = Zotero_Users::getValidUsers($ids);
     return $ids;
 }
Ejemplo n.º 2
0
 public static function getAllAdvanced($userID = false, $params = array(), $permissions = null)
 {
     $buffer = 20;
     $maxTimes = 3;
     $groups = array();
     $start = !empty($params['start']) ? $params['start'] : 0;
     $limit = !empty($params['limit']) ? $params['limit'] + $buffer : false;
     $totalResults = null;
     $times = 0;
     while (true) {
         if ($times > 0) {
             Z_Core::logError('Getting more groups in Zotero_Groups::getAllAdvanced()');
         }
         $sql = "SELECT SQL_CALC_FOUND_ROWS G.groupID, GUO.userID AS ownerUserID FROM groups G\n\t\t\t\t\tJOIN groupUsers GUO ON (G.groupID=GUO.groupID AND GUO.role='owner') ";
         $sqlParams = array();
         if ($userID) {
             $sql .= "JOIN groupUsers GUA ON (G.groupID=GUA.groupID) WHERE GUA.userID=? ";
             $sqlParams[] = $userID;
         }
         $paramSQL = "";
         $includeEmpty = false;
         if (!empty($params['q'])) {
             if (!is_array($params['q'])) {
                 $params['q'] = array($params['q']);
             }
             foreach ($params['q'] as $q) {
                 $field = explode(":", $q);
                 if (sizeOf($field) == 2) {
                     switch ($field[0]) {
                         case 'slug':
                             $includeEmpty = true;
                             break;
                         default:
                             throw new Exception("Cannot search by group field '{$field[0]}'", Z_ERROR_INVALID_GROUP_TYPE);
                     }
                     $paramSQL .= "AND " . $field[0];
                     // If first character is '-', negate
                     $paramSQL .= $field[0][0] == '-' ? '!' : '';
                     $paramSQL .= "=? ";
                     $sqlParams[] = $field[1];
                 } else {
                     $paramSQL .= "AND name LIKE ? ";
                     $sqlParams[] = "%{$q}%";
                 }
             }
         }
         if (!$userID) {
             if ($includeEmpty) {
                 $sql .= "WHERE 1 ";
             } else {
                 // Don't include groups that have never had items
                 $sql .= "JOIN libraries L ON (G.libraryID=L.libraryID)\n\t\t\t\t\t\t\tWHERE L.lastUpdated != '0000-00-00 00:00:00' ";
             }
         }
         $sql .= $paramSQL;
         if (!empty($params['fq'])) {
             if (!is_array($params['fq'])) {
                 $params['fq'] = array($params['fq']);
             }
             foreach ($params['fq'] as $fq) {
                 $facet = explode(":", $fq);
                 if (sizeOf($facet) == 2 && preg_match('/-?GroupType/', $facet[0])) {
                     switch ($facet[1]) {
                         case 'PublicOpen':
                         case 'PublicClosed':
                         case 'Private':
                             break;
                         default:
                             throw new Exception("Invalid group type '{$facet[1]}'", Z_ERROR_INVALID_GROUP_TYPE);
                     }
                     $sql .= "AND type";
                     // If first character is '-', negate
                     $sql .= $facet[0][0] == '-' ? '!' : '';
                     $sql .= "=? ";
                     $sqlParams[] = $facet[1];
                 }
             }
         }
         if (!empty($params['order'])) {
             $order = $params['order'];
             if ($order == 'title') {
                 $order = 'name';
             }
             $sql .= "ORDER BY {$order}";
             if (!empty($params['sort'])) {
                 $sql .= " " . $params['sort'] . " ";
             }
         }
         // Set limit higher than the actual limit, in case some groups are
         // removed during access checks
         //
         // Actual limiting is done below
         if ($limit) {
             $sql .= "LIMIT ?, ?";
             $sqlParams[] = $start;
             $sqlParams[] = $limit;
         }
         $rows = Zotero_DB::query($sql, $sqlParams);
         if (!$rows) {
             break;
         }
         if (!$totalResults) {
             $foundRows = Zotero_DB::valueQuery("SELECT FOUND_ROWS()");
             $totalResults = $foundRows;
         }
         // Include only groups with non-banned owners
         $owners = array();
         foreach ($rows as $row) {
             $owners[] = $row['ownerUserID'];
         }
         $owners = Zotero_Users::getValidUsers($owners);
         $ids = array();
         foreach ($rows as $row) {
             if (!in_array($row['ownerUserID'], $owners)) {
                 $totalResults--;
                 continue;
             }
             $ids[] = $row['groupID'];
         }
         $batchStartPos = sizeOf($groups);
         foreach ($ids as $id) {
             $group = Zotero_Groups::get($id, true);
             $groups[] = $group;
         }
         // Remove groups that can't be accessed
         if ($permissions) {
             for ($i = $batchStartPos; $i < sizeOf($groups); $i++) {
                 $libraryID = (int) $groups[$i]->libraryID;
                 // TEMP: casting shouldn't be necessary
                 if (!$permissions->canAccess($libraryID)) {
                     array_splice($groups, $i, 1);
                     $i--;
                     $totalResults--;
                 }
             }
         }
         $times++;
         if ($times == $maxTimes) {
             Z_Core::logError('Too many queries in Zotero_Groups::getAllAdvanced()');
             break;
         }
         if (empty($params['limit'])) {
             break;
         }
         // If we have enough groups to fill the limit, stop
         if (sizeOf($groups) > $params['limit']) {
             break;
         }
         // If there no more rows, stop
         if ($start + sizeOf($rows) == $foundRows) {
             break;
         }
         // This shouldn't happen
         if ($start + sizeOf($rows) > $foundRows) {
             Z_Core::logError('More rows than $foundRows in Zotero_Groups::getAllAdvanced()');
         }
         $start = $start + sizeOf($rows);
         // Get number we still need plus the buffer or all remaining, whichever is lower
         $limit = min($params['limit'] - sizeOf($groups) + $buffer, $foundRows - $start);
     }
     // TODO: generate previous start value
     if (!$groups) {
         return array('groups' => array(), 'totalResults' => 0);
     }
     // Fake limiting -- we can't just use SQL limit because
     // some groups might be inaccessible
     if (!empty($params['limit'])) {
         $groups = array_slice($groups, 0, $params['limit']);
     }
     $results = array('groups' => $groups, 'totalResults' => $totalResults);
     return $results;
 }
Ejemplo n.º 3
0
 public static function getAllAdvanced($userID = false, $params = array(), $permissions = null)
 {
     $buffer = 20;
     $maxTimes = 3;
     $groups = array();
     $start = !empty($params['start']) ? $params['start'] : 0;
     $limit = !empty($params['limit']) ? $params['limit'] + $buffer : false;
     $totalResults = null;
     $times = 0;
     while (true) {
         if ($times > 0) {
             Z_Core::logError('Getting more groups in Zotero_Groups::getAllAdvanced()');
         }
         $calcFoundRows = !$totalResults;
         $cacheFoundRows = $calcFoundRows && !$userID;
         // If we don't yet have a row count and this isn't a user-specific search,
         // try to get a cached row count.
         if ($cacheFoundRows) {
             $foundRowsCacheKey = self::getCacheComponentFromParam($params, 'q') . "," . self::getCacheComponentFromParam($params, 'fq');
             $foundRowsTTL = 180;
             $foundRowsLockTTL = 10;
             $foundRowsRealTTL = 3600;
             $obj = Z_Core::$MC->get($foundRowsCacheKey);
             if ($obj) {
                 $foundRows = $obj['rows'];
                 $exp = $obj['exp'];
                 // If count was found but is past the expiration time, check if another
                 // request is getting the row count, and fetch it if not
                 if ($exp < time()) {
                     if (!Z_Core::$MC->add($foundRowsCacheKey . "Lock", true, $foundRowsLockTTL)) {
                         $calcFoundRows = false;
                     }
                 } else {
                     $calcFoundRows = false;
                 }
             }
         }
         $sql = "SELECT " . ($calcFoundRows ? "SQL_CALC_FOUND_ROWS " : "") . "G.groupID, GUO.userID AS ownerUserID FROM groups G " . "JOIN groupUsers GUO ON (G.groupID=GUO.groupID AND GUO.role='owner') ";
         $sqlParams = array();
         if ($userID) {
             $sql .= "JOIN groupUsers GUA ON (G.groupID=GUA.groupID) WHERE GUA.userID=? ";
             $sqlParams[] = $userID;
         }
         $paramSQL = "";
         $includeEmpty = false;
         if (!empty($params['q'])) {
             if (!is_array($params['q'])) {
                 $params['q'] = array($params['q']);
             }
             foreach ($params['q'] as $q) {
                 $field = explode(":", $q);
                 if (sizeOf($field) == 2) {
                     switch ($field[0]) {
                         case 'slug':
                             $includeEmpty = true;
                             break;
                         default:
                             throw new Exception("Cannot search by group field '{$field[0]}'", Z_ERROR_INVALID_GROUP_TYPE);
                     }
                     $paramSQL .= "AND " . $field[0];
                     // If first character is '-', negate
                     $paramSQL .= $field[0][0] == '-' ? '!' : '';
                     $paramSQL .= "=? ";
                     $sqlParams[] = $field[1];
                 } else {
                     $paramSQL .= "AND name LIKE ? ";
                     $sqlParams[] = "%{$q}%";
                 }
             }
         }
         if (!$userID) {
             if ($includeEmpty) {
                 $sql .= "WHERE 1 ";
             } else {
                 // Don't include groups that have never had items
                 $sql .= "JOIN libraries L ON (G.libraryID=L.libraryID)\n\t\t\t\t\t\t\tWHERE L.lastUpdated != '0000-00-00 00:00:00' ";
             }
         }
         $sql .= $paramSQL;
         if (!empty($params['fq'])) {
             if (!is_array($params['fq'])) {
                 $params['fq'] = array($params['fq']);
             }
             foreach ($params['fq'] as $fq) {
                 $facet = explode(":", $fq);
                 if (sizeOf($facet) == 2 && preg_match('/-?GroupType/', $facet[0])) {
                     switch ($facet[1]) {
                         case 'PublicOpen':
                         case 'PublicClosed':
                         case 'Private':
                             break;
                         default:
                             throw new Exception("Invalid group type '{$facet[1]}'", Z_ERROR_INVALID_GROUP_TYPE);
                     }
                     $sql .= "AND type";
                     // If first character is '-', negate
                     $sql .= $facet[0][0] == '-' ? '!' : '';
                     $sql .= "=? ";
                     $sqlParams[] = $facet[1];
                 }
             }
         }
         if (!empty($params['sort'])) {
             $order = $params['sort'];
             if ($order == 'title') {
                 $order = 'name';
             }
             $sql .= "ORDER BY {$order}";
             if (!empty($params['direction'])) {
                 $sql .= " " . $params['direction'] . " ";
             }
         }
         // Limit is set $buffer higher than the actual limit, in case some groups are
         // removed during access checks
         //
         // Actual limiting is done below
         if ($limit) {
             $sql .= "LIMIT ?, ?";
             $sqlParams[] = $start;
             $sqlParams[] = $limit;
         }
         $rows = Zotero_DB::query($sql, $sqlParams);
         if (!$rows) {
             break;
         }
         if (is_null($totalResults)) {
             if ($calcFoundRows) {
                 $foundRows = Zotero_DB::valueQuery("SELECT FOUND_ROWS()");
                 // Cache found rows count, and store earlier expiration time so that one
                 // request can trigger a recalculation before cached value expires
                 if ($cacheFoundRows) {
                     Z_Core::$MC->set($foundRowsCacheKey, ['rows' => $foundRows, 'exp' => time() + $foundRowsTTL], $foundRowsRealTTL);
                 }
             }
             $totalResults = $foundRows;
         }
         // Include only groups with non-banned owners
         $owners = array();
         foreach ($rows as $row) {
             $owners[] = $row['ownerUserID'];
         }
         $owners = Zotero_Users::getValidUsers($owners);
         $ids = array();
         foreach ($rows as $row) {
             if (!in_array($row['ownerUserID'], $owners)) {
                 $totalResults--;
                 continue;
             }
             $ids[] = $row['groupID'];
         }
         $batchStartPos = sizeOf($groups);
         foreach ($ids as $id) {
             $group = Zotero_Groups::get($id, true);
             $groups[] = $group;
         }
         // Remove groups that can't be accessed
         if ($permissions) {
             for ($i = $batchStartPos; $i < sizeOf($groups); $i++) {
                 if (!$permissions->canAccess($groups[$i]->libraryID, 'view')) {
                     array_splice($groups, $i, 1);
                     $i--;
                     $totalResults--;
                 }
             }
         }
         $times++;
         if ($times == $maxTimes) {
             Z_Core::logError('Too many queries in Zotero_Groups::getAllAdvanced()');
             break;
         }
         if (empty($params['limit'])) {
             break;
         }
         // If we have enough groups to fill the limit, stop
         if (sizeOf($groups) > $params['limit']) {
             break;
         }
         // If there no more rows, stop
         if ($start + sizeOf($rows) >= $foundRows) {
             break;
         }
         $start = $start + sizeOf($rows);
         // Get number we still need plus the buffer or all remaining, whichever is lower
         $limit = min($params['limit'] - sizeOf($groups) + $buffer, $foundRows - $start);
     }
     // TODO: generate previous start value
     if (!$groups) {
         return array('results' => array(), 'total' => 0);
     }
     // Fake limiting -- we can't just use SQL limit because
     // some groups might be inaccessible
     if (!empty($params['limit'])) {
         $groups = array_slice($groups, 0, $params['limit']);
     }
     $results = array('results' => $groups, 'total' => $totalResults);
     return $results;
 }