Returns an array of record hashes with the column names as keys and
column values as values.
/** * Ensure that an array of users exist in storage. Create any that don't, * return user_ids for all. * * @param array $users An array of users. Values typed as an integer * are assumed to already be an user_id. * * @return array An array of user_ids. */ public function ensureUsers($users) { if (!is_array($users)) { $users = array($users); } $userIds = array(); $userName = array(); // Anything already typed as an integer is assumed to be a user id. foreach ($users as $userIndex => $user) { if (is_int($user)) { $userIds[$userIndex] = $user; } else { $userName[$user] = $userIndex; } } // Get the ids for any users that already exist. try { if (count($userName)) { $userName; $sql = 'SELECT user_id, user_name FROM ' . $this->_t('users') . ' WHERE user_name IN (' . implode(',', array_map(array($this, 'toDriver'), array_keys($userName))) . ')'; foreach ($this->_db->selectAll($sql) as $row) { $userIndex = $userName[$row['user_name']]; unset($userName[$row['user_name']]); $userIds[$userIndex] = $row['user_id']; } } // Create any users that didn't already exist foreach ($userName as $user => $userIndex) { $userIds[$userIndex] = $this->_db->insert('INSERT INTO ' . $this->_t('users') . ' (user_name) VALUES (' . $this->toDriver($user) . ')'); } } catch (Horde_Db_Exception $e) { throw new Content_Exception($e); } return $userIds; }
/** * Loads all rules from the DB backend. * * @param boolean $readonly Whether to disable any write operations. */ public function init($readonly = false) { $query = sprintf('SELECT * FROM %s WHERE rule_owner = ? ORDER BY rule_order', $this->_params['table_rules']); $values = array(Ingo::getUser()); try { $result = $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Ingo_Exception($e); } $data = array(); foreach ($result as $row) { $data[$row['rule_order']] = array('id' => (int) $row['rule_id'], 'name' => Horde_String::convertCharset($row['rule_name'], $this->_params['charset'], 'UTF-8'), 'action' => (int) $row['rule_action'], 'action-value' => Horde_String::convertCharset($row['rule_value'], $this->_params['charset'], 'UTF-8'), 'flags' => (int) $row['rule_flags'], 'conditions' => empty($row['rule_conditions']) ? null : Horde_String::convertCharset(unserialize($row['rule_conditions']), $this->_params['charset'], 'UTF-8'), 'combine' => (int) $row['rule_combine'], 'stop' => (bool) $row['rule_stop'], 'disable' => !(bool) $row['rule_active']); } $this->setFilterlist($data); if (empty($data) && !$readonly) { $data = @unserialize($GLOBALS['prefs']->getDefault('rules')); if ($data) { foreach ($data as $val) { $this->addRule($val, false); } } else { $this->addRule(array('name' => 'Whitelist', 'action' => Ingo_Storage::ACTION_WHITELIST), false); $this->addRule(array('name' => 'Vacation', 'action' => Ingo_Storage::ACTION_VACATION, 'disable' => true), false); $this->addRule(array('name' => 'Blacklist', 'action' => Ingo_Storage::ACTION_BLACKLIST), false); $this->addRule(array('name' => 'Spam Filter', 'action' => Ingo_Storage::ACTION_SPAM, 'disable' => true), false); $this->addRule(array('name' => 'Forward', 'action' => Ingo_Storage::ACTION_FORWARD), false); } } }
/** * Retrieves the foos from the database. * * @throws Kolab_Exception */ public function retrieve() { /* Build the SQL query. */ $query = 'SELECT * FROM ' . $this->_params['table'] . ' WHERE foo = ?'; $values = array($this->_params['bar']); /* Execute the query. */ try { $rows = $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Kolab_Exception($e); } /* Store the retrieved values in the foo variable. */ $this->_foo = array_merge($this->_foo, $rows); }
/** * Retrieves all of the notes of the current notepad from the backend. * * @throws Mnemo_Exception */ public function retrieve() { $query = sprintf('SELECT * FROM %s WHERE memo_owner = ?', $this->_table); $values = array($this->_notepad); try { $rows = $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Mnemo_Exception($e->getMessage()); } // Store the retrieved values in a fresh list. $this->_memos = array(); foreach ($rows as $row) { $this->_memos[$row['memo_id']] = $this->_buildNote($row); } }
/** * Retrieves one or multiple tasks from the database. * * @param mixed string|array $taskIds The ids of the task to retrieve. * @param string $column The column name to search for the ID. * * @return Nag_Task A Nag_Task object. * @throws Horde_Exception_NotFound * @throws Nag_Exception */ protected function _getBy($taskIds, $column, array $tasklists = null) { if (!is_array($taskIds)) { $query = 'SELECT * FROM nag_tasks WHERE ' . $column . ' = ?'; $values = array($taskIds); } else { if (empty($taskIds)) { throw new InvalidArgumentException('Must specify at least one task id'); } $query = 'SELECT * FROM nag_tasks WHERE ' . $column . ' IN (' . implode(',', array_fill(0, count($taskIds), '?')) . ')'; $values = $taskIds; } if (!empty($tasklists)) { $query .= ' AND task_owner IN (' . implode(',', array_fill(0, count($tasklists), '?')) . ')'; $values = array_merge($values, $tasklists); } try { $rows = $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Nag_Exception($e); } if (!$rows) { throw new Horde_Exception_NotFound(_("Tasks not found")); } if (!is_array($taskIds)) { $results = new Nag_Task($this, $this->_buildTask(reset($rows))); $this->_tasklist = $results->tasklist; } else { $results = new Nag_Task(); foreach ($rows as $row) { $results->add(new Nag_Task($this, $this->_buildTask($row))); } } return $results; }
/** * Fetch client settings from storage. * * @param integer the client id * * @return array A hash of client settings. * @throws Hermes_Exception */ public function getClientSettings($clientID) { $clients = Hermes::listClients(); if (empty($clientID) || !isset($clients[$clientID])) { throw new Horde_Exception_NotFound('Does not exist'); } $sql = 'SELECT clientjob_id, clientjob_enterdescription,' . ' clientjob_exportid FROM hermes_clientjobs' . ' WHERE clientjob_id = ?'; $values = array($clientID); try { $rows = $this->_db->selectAll($sql, $values); } catch (Horde_Db_Exception $e) { throw new Hermes_Exception($e); } $clientJob = array(); foreach ($rows as $row) { $clientJob[$row['clientjob_id']] = array($row['clientjob_enterdescription'], $row['clientjob_exportid']); } if (isset($clientJob[$clientID])) { $settings = array('id' => $clientID, 'enterdescription' => $clientJob[$clientID][0], 'exportid' => $this->_convertFromDriver($clientJob[$clientID][1])); } else { $settings = array('id' => $clientID, 'enterdescription' => 1, 'exportid' => null); } $settings['name'] = $clients[$clientID]; return $settings; }
/** * Return a list of valid locks with the option to limit the results * by principal, scope and/or type. * * @see Horde_Lock_Base::getLocks() */ public function getLocks($scope = null, $principal = null, $type = null) { $now = time(); $sql = 'SELECT lock_id, lock_owner, lock_scope, lock_principal, ' . 'lock_origin_timestamp, lock_update_timestamp, ' . 'lock_expiry_timestamp, lock_type FROM ' . $this->_params['table'] . ' WHERE (lock_expiry_timestamp >= ? OR lock_expiry_timestamp = ?)'; $values = array($now, Horde_Lock::PERMANENT); // Check to see if we need to filter the results if (!empty($principal)) { $sql .= ' AND lock_principal = ?'; $values[] = $principal; } if (!empty($scope)) { $sql .= ' AND lock_scope = ?'; $values[] = $scope; } if (!empty($type)) { $sql .= ' AND lock_type = ?'; $values[] = $type; } try { $result = $this->_db->selectAll($sql, $values); } catch (Horde_Db_Exception $e) { throw new Horde_Lock_Exception($e); } $locks = array(); foreach ($result as $row) { $locks[$row['lock_id']] = $row; } return $locks; }
/** * Ensure that an array of objects exist in storage. Create any that don't, * return object_ids for all. All objects in the $objects array must be * of the same content type. * * @param mixed $objects An array of objects (or single obejct value). * Values typed as an integer are assumed to already * be an object_id. * @param mixed $type Either a string type_name or integer type_id * * @return array An array of object_ids. */ public function ensureObjects($objects, $type) { if (!is_array($objects)) { $objects = array($objects); } $objectIds = array(); $objectName = array(); $type = current($this->_typeManager->ensureTypes($type)); // Anything already typed as an integer is assumed to be an object id. foreach ($objects as $objectIndex => $object) { if (is_int($object)) { $objectIds[$objectIndex] = $object; } else { $objectName[$object] = $objectIndex; } } // Get the ids for any objects that already exist. try { if (count($objectName)) { $rows = $this->_db->selectAll('SELECT object_id, object_name FROM ' . $this->_t('objects') . ' WHERE object_name IN (' . implode(',', array_map(array($this->_db, 'quoteString'), array_keys($objectName))) . ') AND type_id = ' . $type); foreach ($rows as $row) { $objectIndex = $objectName[$row['object_name']]; unset($objectName[$row['object_name']]); $objectIds[$objectIndex] = $row['object_id']; } } // Create any objects that didn't already exist foreach ($objectName as $object => $objectIndex) { $objectIds[$objectIndex] = $this->_db->insert('INSERT INTO ' . $this->_t('objects') . ' (object_name, type_id) VALUES (' . $this->_db->quoteString($object) . ', ' . $type . ')'); } } catch (Horde_Db_Exception $e) { throw new Content_Exception($e); } return $objectIds; }
/** * Reads the given data from the SQL database and returns the results. * * @param string $key The primary key field to use. * @param mixed $ids The ids of the contacts to load. * @param string $owner Only return contacts owned by this user. * @param array $fields List of fields to return. * @param array $blobFields Array of fields containing binary data. * @param array $dateFields Array of fields containing date data. * @since 4.2.0 * * @return array Hash containing the search results. * @throws Turba_Exception */ protected function _read($key, $ids, $owner, array $fields, array $blobFields = array(), array $dateFields = array()) { $values = array(); $in = ''; if (is_array($ids)) { if (!count($ids)) { return array(); } foreach ($ids as $id) { $in .= empty($in) ? '?' : ', ?'; $values[] = $this->_convertToDriver($id); } $where = $key . ' IN (' . $in . ')'; } else { $where = $key . ' = ?'; $values[] = $this->_convertToDriver($ids); } if (isset($this->map['__owner'])) { $where .= ' AND ' . $this->map['__owner'] . ' = ?'; $values[] = $this->_convertToDriver($owner); } if (!empty($this->_params['filter'])) { $where .= ' AND ' . $this->_params['filter']; } $query = 'SELECT ' . implode(', ', $fields) . ' FROM ' . $this->_params['table'] . ' WHERE ' . $where; try { return $this->_parseRead($blobFields, $this->_db->selectAll($query, $values), $dateFields); } catch (Horde_Db_Exception $e) { throw new Turba_Exception(_("Server error when performing search.")); } }
/** * Fetches the fields for a particular form. * * @param integer $form_id The form id of the form to return. * * @return array The fields. * @throws Ulaform_Exception */ public function getFields($form_id, $field_id = null) { $values = array($form_id); $sql = 'SELECT field_id, form_id, field_name, field_order, field_label, field_type, ' . ' field_params, field_required, field_readonly, field_desc FROM ulaform_fields ' . ' WHERE form_id = ?'; if (!is_null($field_id)) { $sql .= ' AND field_id = ?'; $values[] = (int) $field_id; } $sql .= ' ORDER BY field_order'; try { $results = $this->_db->selectAll($sql, $values); } catch (Horde_Db_Exception $e) { throw new Ulaform_Exception($e); } $fields = array(); foreach ($results as $field) { /* If no internal name set, generate one using field_id. */ if (empty($field['field_name'])) { $field['field_name'] = 'field_' . $field['field_id']; } /* Check if any params and unserialize, otherwise return null. */ if (!empty($field['field_params'])) { $field['field_params'] = Horde_Serialize::unserialize($field['field_params'], Horde_Serialize::UTF7_BASIC); } else { $field['field_params'] = null; } $fields[] = $field; } return $fields; }
/** * Retrieves the foos from the database. * * @throws Skeleton_Exception */ public function retrieve() { /* Build the SQL query. */ // Unrestricted query $query = 'SELECT * FROM skeleton_items'; // Restricted query alternative //$query = 'SELECT * FROM skeleton_items WHERE foo = ?'; //$values = array($this->_params['bar']); /* Execute the query. */ try { $rows = $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Skeleton_Exception($e); } /* Store the retrieved values in the foo variable. */ $this->_foo = array_merge($this->_foo, $rows); }
/** */ public function get($scope_ob) { $charset = $this->_db->getOption('charset'); $query = 'SELECT pref_name, pref_value FROM ' . $this->_params['table'] . ' ' . 'WHERE pref_uid = ? AND pref_scope = ?'; $values = array($this->_params['user'], $scope_ob->scope); try { $result = $this->_db->selectAll($query, $values); $columns = $this->_db->columns($this->_params['table']); } catch (Horde_Db_Exception $e) { throw new Horde_Prefs_Exception($e); } foreach ($result as $row) { $name = trim($row['pref_name']); $value = $columns['pref_value']->binaryToString($row['pref_value']); $scope_ob->set($name, Horde_String::convertCharset($value, $charset, 'UTF-8')); } return $scope_ob; }
/** * Returns a Horde_History_Log corresponding to the named history entry, * with the data retrieved appropriately. * * @param string $guid The name of the history entry to retrieve. * * @return Horde_History_Log A Horde_History_Log object. * @throws Horde_History_Exception */ public function _getHistory($guid) { try { $rows = $this->_db->selectAll('SELECT * FROM horde_histories WHERE object_uid = ?', array($guid)); } catch (Horde_Db_Exception $e) { throw new Horde_History_Exception($e); } return new Horde_History_Log($guid, $rows); }
/** * Fetches the a list of available forms to use. * * @return array An array of the available forms. * @throws Ulaform_Exception */ public function getAvailableForms() { /* Fetch a list of all forms for now. */ $sql = 'SELECT form_id, user_uid, form_name, form_action, form_params,' . ' form_onsubmit FROM ulaform_forms'; try { return $this->_db->selectAll($sql); } catch (Horde_Db_Exception $e) { throw new Ulaform_Exception($e->getMessage()); } }
/** * Get an event or events with the given UID value. * * @param string $uid The UID to match * @param array $calendars A restricted array of calendar ids to search * @param boolean $getAll Return all matching events? * * @return Kronolith_Event * @throws Kronolith_Exception * @throws Horde_Exception_NotFound */ public function getByUID($uid, $calendars = null, $getAll = false) { $query = 'SELECT event_id, event_uid, calendar_id, event_description,' . ' event_location, event_private, event_status, event_attendees,' . ' event_title, event_recurcount, event_url, event_timezone,' . ' event_recurtype, event_recurenddate, event_recurinterval,' . ' event_recurdays, event_start, event_end, event_allday,' . ' event_alarm, event_alarm_methods, event_modified,' . ' event_exceptions, event_creator_id, event_resources, event_baseid,' . ' event_exceptionoriginaldate, event_organizer FROM kronolith_events' . ' WHERE event_uid = ?'; $values = array((string) $uid); /* Optionally filter by calendar */ if (!empty($calendars)) { if (!count($calendars)) { throw new Kronolith_Exception(_("No calendars to search")); } $query .= ' AND calendar_id IN (?' . str_repeat(', ?', count($calendars) - 1) . ')'; $values = array_merge($values, $calendars); } try { $events = $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Kronolith_Exception($e); } if (!count($events)) { throw new Horde_Exception_NotFound(sprintf(_("%s not found"), $uid)); } $eventArray = array(); foreach ($events as $event) { /* Convert TEXT/CLOB fields. */ $event = $this->convertBlobs($event); $this->open($event['calendar_id']); $this->_cache[$this->calendar][$event['event_id']] = new $this->_eventClass($this, $event); $eventArray[] = $this->_cache[$this->calendar][$event['event_id']]; } if ($getAll) { return $eventArray; } /* First try the user's own calendars. */ $ownerCalendars = Kronolith::listInternalCalendars(true, Horde_Perms::READ); $event = null; foreach ($eventArray as $ev) { if (isset($ownerCalendars[$ev->calendar])) { $event = $ev; break; } } /* If not successful, try all calendars the user has access too. */ if (empty($event)) { $readableCalendars = Kronolith::listInternalCalendars(false, Horde_Perms::READ); foreach ($eventArray as $ev) { if (isset($readableCalendars[$ev->calendar])) { $event = $ev; break; } } } if (empty($event)) { $event = $eventArray[0]; } return $event; }
/** * Search for a textual location string from the passed in search token. * Used for location autocompletion. * * @param string $search Search fragment for autocompleting location strings * * @return array The results * @throws Ansel_Exception */ public function searchLocations($search = '') { $sql = 'SELECT DISTINCT image_location, image_latitude, image_longitude FROM ansel_images WHERE LENGTH(image_location) > 0'; if (strlen($search)) { $sql .= ' AND image_location LIKE ' . $this->_db->quoteString("{$search}%"); } try { return $this->_db->selectAll($sql); } catch (Horde_Db_Exception $e) { throw new Ansel_Exception($e); } }
/** * Get the users who have most recently tagged objects. * * @param array $args Search criteria: * limit Maximum number of users to return. * offset Offset the results. Only useful for paginating, and not recommended. * typeId Only return users who have tagged objects of a specific object type. * * @return array */ public function getRecentUsers($args = array()) { $sql = 'SELECT tagged.user_id AS user_id, MAX(created) AS created FROM ' . $this->_t('tagged') . ' tagged'; if (isset($args['typeId'])) { $args['typeId'] = current($this->_typeManager->ensureTypes($args['typeId'])); $sql .= ' INNER JOIN ' . $this->_t('objects') . ' objects ON tagged.object_id = objects.object_id AND objects.type_id = ' . (int) $args['typeId']; } $sql .= ' GROUP BY tagged.user_id ORDER BY created DESC'; if (isset($args['limit'])) { $sql = $this->_db->addLimitOffset($sql, array('limit' => $args['limit'], 'offset' => isset($args['offset']) ? $args['offset'] : 0)); } return $this->_db->selectAll($sql); }
/** * Returns a list of all global alarms from the backend. * * @return array A list of alarm hashes. * @throws Horde_Alarm_Exception */ protected function _global() { $query = sprintf('SELECT alarm_id, alarm_uid, alarm_start, alarm_end, alarm_methods, alarm_params, alarm_title, alarm_text, alarm_snooze, alarm_internal FROM %s WHERE alarm_uid IS NULL OR alarm_uid = \'\' ORDER BY alarm_start, alarm_end', $this->_params['table']); try { $result = $this->_db->selectAll($query); } catch (Horde_Db_Exception $e) { throw new Horde_Alarm_Exception(Horde_Alarm_Translation::t("Server error when querying database.")); } $alarms = array(); foreach ($result as $val) { $alarms[] = $this->_getHash($val); } return $alarms; }
public function getMany($num = 50) { $tasks = array(); $values = array(); $query = 'SELECT * FROM horde_queue_tasks where task_queue = ? ORDER BY task_id LIMIT ?'; $values[] = $this->_queue; $values[] = $num; try { $rows = $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Horde_Queue_Exception($e); } $query = 'DELETE FROM horde_queue_tasks WHERE task_id = ?'; foreach ($rows as $row) { $tasks[] = unserialize($row['task_fields']); // TODO: Evaluate if a single call for all IDs is faster for various scenarios try { $rows = $this->_db->execute($query, array($row['task_id'])); } catch (Horde_Db_Exception $e) { throw new Horde_Queue_Exception($e); } } return $tasks; }
/** * Returns an array of all system shares. * * @return array All system shares. * @throws Horde_Share_Exception */ public function listSystemShares() { $query = 'SELECT * FROM ' . $this->_table . ' WHERE share_owner IS NULL'; try { $rows = $this->_db->selectAll($query); } catch (Horde_Db_Exception $e) { throw new Horde_Share_Exception($e->getMessage()); } $sharelist = array(); foreach ($rows as $share) { $data = $this->_fromDriverCharset($share); $this->_getSharePerms($data); $sharelist[$data['share_name']] = $this->_createObject($data); } return $sharelist; }
/** * Lists all alarms near $date. * * @param integer $date The unix epoch time to check for alarms. * * @return array An array of tasks that have alarms that match. * @throws Nag_Exception */ public function listAlarms($date) { $q = 'SELECT * FROM ' . $this->_params['table'] . ' WHERE task_owner = ?' . ' AND task_alarm > 0' . ' AND (task_due - (task_alarm * 60) <= ?)' . ' AND task_completed = 0'; $values = array($this->_tasklist, $date); try { $result = $this->_db->selectAll($q, $values); } catch (Horde_Db_Exception $e) { throw new Nag_Exception($e->getMessage()); } $tasks = array(); foreach ($result as $row) { $task = new Nag_Task($this, $this->_buildTask($row)); if ($task->getNextDue()->before($date + $task->alarm * 60)) { $tasks[$row['task_id']] = $task; } } return $tasks; }
/** * List all devices that we know about. * * @param string $user The username to list devices for. If empty, will * return all devices. * @param array $filter An array of optional filters where the keys are * field names and the values are values to match. * * @return array An array of device hashes * @throws Horde_ActiveSync_Exception */ public function listDevices($user = null, $filter = array()) { $query = 'SELECT d.device_id AS device_id, device_type, device_agent,' . ' device_policykey, device_rwstatus, device_user, device_properties FROM ' . $this->_syncDeviceTable . ' d INNER JOIN ' . $this->_syncUsersTable . ' u ON d.device_id = u.device_id'; $values = array(); $glue = false; if (!empty($user)) { $query .= ' WHERE u.device_user = ?'; $values[] = $user; $glue = true; } $explicit_fields = array('device_id', 'device_type', 'device_agent', 'device_user'); foreach ($filter as $key => $value) { if (in_array($key, $explicit_fields)) { $query .= ($glue ? ' AND ' : ' WHERE ') . 'd.' . $key . ' LIKE ?'; $values[] = $value . '%'; } } try { return $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } }
/** * Fetches a list of forums. * * @param integer $forums Forums to format * * @return array An array of forums. * @throws Agora_Exception */ protected function _formatForums($forums) { /* Get moderators */ foreach ($forums as $forum) { $forums_list[] = $forum['forum_id']; } $sql = 'SELECT forum_id, horde_uid' . ' FROM agora_moderators WHERE forum_id IN (' . implode(',', array_values($forums_list)) . ')'; try { $moderators = $this->_db->selectAll($sql); } catch (Horde_Db_Exception $e) { throw new Agora_Exception($e->getMessage()); } foreach ($forums as $key => $forum) { $forums[$key]['forum_name'] = $this->convertFromDriver($forums[$key]['forum_name']); $forums[$key]['forum_description'] = $this->convertFromDriver($forums[$key]['forum_description']); foreach ($moderators as $moderator) { if ($moderator['forum_id'] == $forum['forum_id']) { $forums[$key]['moderators'][] = $moderator['horde_uid']; } } } return $forums; }
/** * Returns a Horde_History_Log corresponding to the named history entry, * with the data retrieved appropriately. * * @param string $guid The name of the history entry to retrieve. * * @return Horde_History_Log A Horde_History_Log object. * * @throws Horde_History_Exception */ public function _getHistory($guid) { $rows = $this->_db->selectAll('SELECT * FROM horde_histories WHERE object_uid = ?', array($guid)); return new Horde_History_Log($guid, $rows); }
/** * Returns an array of record hashes with the column names as keys and * column values as values. * * @param string $sql SQL statement. * @param mixed $arg1 Either an array of bound parameters or a query * name. * @param string $arg2 If $arg1 contains bound parameters, the query * name. * * @return array * @throws Horde_Db_Exception */ public function selectAll($sql, $arg1 = null, $arg2 = null) { $result = $this->_read->selectAll($sql, $arg1, $arg2); $this->_lastQuery = $this->_read->getLastQuery(); return $result; }
/** * Garbage collector - clean up from previous sync requests. * * @param string $syncKey The sync key * * @throws Horde_ActiveSync_Exception */ protected function _gc($syncKey) { if (!preg_match('/^\\{([0-9A-Za-z-]+)\\}([0-9]+)$/', $syncKey, $matches)) { return; } $guid = $matches[1]; $n = $matches[2]; // Clean up all but the last 2 syncs for any given sync series, this // ensures that we can still respond to SYNC requests for the previous // key if the client never received the new key in a SYNC response. $sql = 'SELECT sync_key FROM ' . $this->_syncStateTable . ' WHERE sync_devid = ? AND sync_folderid = ?'; $values = array($this->_deviceInfo->id, !empty($this->_collection['id']) ? $this->_collection['id'] : Horde_ActiveSync::CHANGE_TYPE_FOLDERSYNC); try { $results = $this->_db->selectAll($sql, $values); } catch (Horde_Db_Exception $e) { $this->_logger->err(sprintf('[%s] %s', $this->_procid, $e->getMessage())); throw new Horde_ActiveSync_Exception($e); } $remove = array(); $guids = array($guid); foreach ($results as $oldkey) { if (preg_match('/^\\{([0-9A-Za-z-]+)\\}([0-9]+)$/', $oldkey['sync_key'], $matches)) { if ($matches[1] == $guid && $matches[2] < $n - 1) { $remove[] = $oldkey['sync_key']; } } else { /* stale key from previous key series */ $remove[] = $oldkey['sync_key']; $guids[] = $matches[1]; } } if (count($remove)) { $sql = 'DELETE FROM ' . $this->_syncStateTable . ' WHERE sync_key IN (' . str_repeat('?,', count($remove) - 1) . '?)'; try { $this->_db->delete($sql, $remove); } catch (Horde_Db_Exception $e) { $this->_logger->err(sprintf('[%s] %s', $this->_procid, $e->getMessage())); throw new Horde_ActiveSync_Exception($e); } } // Also clean up the map table since this data is only needed for one // SYNC cycle. Keep the same number of old keys for the same reasons as // above. foreach (array($this->_syncMapTable, $this->_syncMailMapTable) as $table) { $remove = array(); $sql = 'SELECT DISTINCT sync_key FROM ' . $table . ' WHERE sync_devid = ? AND sync_user = ?'; try { $maps = $this->_db->selectValues($sql, array($this->_deviceInfo->id, $this->_deviceInfo->user)); } catch (Horde_Db_Exception $e) { $this->_logger->err(sprintf('[%s] %s', $this->_procid, $e->getMessage())); throw new Horde_ActiveSync_Exception($e); } foreach ($maps as $key) { if (preg_match('/^\\{([0-9A-Za-z-]+)\\}([0-9]+)$/', $key, $matches)) { if ($matches[1] == $guid && $matches[2] < $n) { $remove[] = $key; } } } if (count($remove)) { $sql = 'DELETE FROM ' . $table . ' WHERE sync_key IN (' . str_repeat('?,', count($remove) - 1) . '?)'; try { $this->_db->delete($sql, $remove); } catch (Horde_Db_Exception $e) { $this->_logger->err(sprintf('[%s] %s', $this->_procid, $e->getMessage())); throw new Horde_ActiveSync_Exception($e); } } } }