Index: contrib/search_api_facets/search_api_facets.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/search_api/contrib/search_api_facets/Attic/search_api_facets.install,v retrieving revision 1.1.2.5 diff -u -r1.1.2.5 search_api_facets.install --- contrib/search_api_facets/search_api_facets.install 30 Nov 2010 16:39:48 -0000 1.1.2.5 +++ contrib/search_api_facets/search_api_facets.install 30 Nov 2010 17:03:18 -0000 @@ -8,6 +8,12 @@ $schema['search_api_facet'] = array( 'description' => 'Stores all activated or configured facets of a site.', 'fields' => array( + 'id' => array( + 'description' => 'The primary identifier for a facet.', + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), 'delta' => array( 'description' => "The facet block's {block}.delta.", 'type' => 'varchar', @@ -51,7 +57,10 @@ 'field' => array('index_id', array('field', 50)), 'enabled' => array('enabled'), ), - 'primary key' => array('delta'), + 'unique keys' => array( + 'delta' => array('delta'), + ), + 'primary key' => array('id'), ); return $schema; @@ -77,12 +86,9 @@ } /** - * Implements hook_update_N(). - * * Make {search_api_facet}.index_id the index' machine name. */ function search_api_facets_update_7101() { - // Update of search_api_item: db_drop_index('search_api_facet', 'field'); $spec = array( 'description' => 'The {search_api_index}.machine_name this facet belongs to.', @@ -103,3 +109,36 @@ ->execute(); } } + +/** + * Add a numeric id for facets, as required for all entities. + */ +function search_api_facets_update_7102() { + db_drop_primary_key('search_api_facet'); + $spec = array( + 'description' => 'The primary identifier for a facet.', + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + ); + $keys_new = array( + 'unique keys' => array( + 'delta' => array('delta'), + ), + 'primary key' => array('id'), + ); + db_add_field('search_api_facet', 'id', $spec, $keys_new); + $deltas = db_select('search_api_facet', 'f') + ->fields('f', array('delta')) + ->execute() + ->fetchCol(); + $i = 0; + foreach ($deltas as $delta) { + db_update('search_api_facet') + ->fields(array( + 'id' => ++$i, + )) + ->condition('delta', $delta) + ->execute(); + } +} Index: contrib/search_api_facets/search_api_facets.admin.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/search_api/contrib/search_api_facets/Attic/search_api_facets.admin.inc,v retrieving revision 1.1.2.8 diff -u -r1.1.2.8 search_api_facets.admin.inc --- contrib/search_api_facets/search_api_facets.admin.inc 28 Oct 2010 20:43:12 -0000 1.1.2.8 +++ contrib/search_api_facets/search_api_facets.admin.inc 30 Nov 2010 17:03:18 -0000 @@ -17,7 +17,7 @@ // We can't offer any facets, but maybe the user can delete old facet data. drupal_set_message(t("The server this index currently lies on doesn't support facets. " . 'To use facets, you will have to move this index to a server supporting this feature.'), 'error'); - if (db_query('SELECT COUNT(1) FROM {search_api_facet} WHERE index_id = :id', array(':id' => $index->machine_name))->fetchField()) { + if (search_api_facet_load(array('index_id' => $index->machine_name))) { $form['description'] = array( '#type' => 'item', '#title' => t('Delete facet settings'), @@ -74,13 +74,13 @@ $type = search_api_extract_inner_type($field['type']); $type = isset($types[$type]) ? $types[$type] : $type; if (empty($facets[$key])) { - $facets[$key][] = (object) array( + $facets[$key][] = new SearchApiFacet(array( 'index_id' => $index->machine_name, 'field' => $key, 'name' => t('!index: Filter on !field', array('!field' => $field['name'], '!index' => $index->name)), 'enabled' => 0, 'options' => array(), - ); + )); } foreach ($facets[$key] as $i => $facet) { $k = $i ? "$key-$i" : $key; @@ -188,7 +188,7 @@ $f = clone $f; $f->enabled = $v['enabled']; $f->name = $v['name']; - search_api_facet_save($f); + $f->save(); ++$count; } if ($v['clone']) { @@ -196,7 +196,7 @@ unset($f->delta); $f->name = t('!index: Filter on !field #!num', array('!field' => $index->options['fields'][$f->field]['name'], '!index' => $index->name, '!num' => $c + 1)); - search_api_facet_save($f); + $f->save(); ++$clone_count; } } Index: contrib/search_api_facets/search_api_facets.info =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/search_api/contrib/search_api_facets/Attic/search_api_facets.info,v retrieving revision 1.1.2.5 diff -u -r1.1.2.5 search_api_facets.info --- contrib/search_api_facets/search_api_facets.info 30 Nov 2010 16:48:04 -0000 1.1.2.5 +++ contrib/search_api_facets/search_api_facets.info 30 Nov 2010 17:03:18 -0000 @@ -8,6 +8,7 @@ package = Search files[] = search_api_facets.admin.inc +files[] = search_api_facets.entity.inc files[] = search_api_facets.install files[] = search_api_facets.module files[] = search_api_facets.theme.inc Index: contrib/search_api_facets/search_api_facets.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/search_api/contrib/search_api_facets/Attic/search_api_facets.module,v retrieving revision 1.1.2.26 diff -u -r1.1.2.26 search_api_facets.module --- contrib/search_api_facets/search_api_facets.module 30 Nov 2010 16:39:48 -0000 1.1.2.26 +++ contrib/search_api_facets/search_api_facets.module 30 Nov 2010 17:03:18 -0000 @@ -72,6 +72,28 @@ } /** + * Implements hook_entity_info(). + */ +function search_api_facets_entity_info() { + $info['search_api_facet'] = array( + 'label' => t('Search facet'), + 'controller class' => 'EntityAPIController', + 'entity class' => 'SearchApiFacet', + 'base table' => 'search_api_facet', + 'uri callback' => 'search_api_facet_url', + 'module' => 'search_api_facets', + 'exportable' => TRUE, + 'entity keys' => array( + 'id' => 'id', + 'name' => 'delta', + 'label' => 'name', + ), + ); + + return $info; +} + +/** * Implements hook_permission(). */ function search_api_facets_permission() { @@ -238,7 +260,7 @@ } if ($options != $facet->options) { $facet->options = $options; - search_api_facet_save($facet); + $facet->save(); } } @@ -286,7 +308,7 @@ if (empty($options['type'])) { _search_api_facets_refresh_type($facet, $options); $facet->options = $options; - search_api_facet_save($facet); + $facet->save(); } $type = $options['type']; $values = isset($options['options']) ? $options['options'] : array(); @@ -475,7 +497,7 @@ $facet = reset($facets); if (empty($facet->options['type'])) { _search_api_facets_refresh_type($facet, $facet->options); - search_api_facet_save($facet); + $facet->save(); } $type = $facet->options['type']; $values = isset($facet->options['options']) ? $facet->options['options'] : array(); @@ -602,19 +624,19 @@ function search_api_facets_search_api_index_update(SearchApiIndex $index, $op = 'edit') { $id = $index->machine_name; if ($op == 'enable') { - if (db_query('SELECT COUNT(1) FROM {search_api_facet} WHERE index_id = :id', array(':id' => $id))->fetchField()) { + if (search_api_facet_load(array('index_id' => $id))) { drupal_set_message(t('There are saved facets for this index. ' . 'Go to the facet page to enable them.', array('!url' => 'admin/config/search/search_api/index/' . $id . '/facets'))); } } elseif ($op == 'disable') { - $count = db_update('search_api_facet') - ->fields(array('enabled' => 0)) - ->condition('index_id', $id) - ->execute(); - if ($count) { - drupal_set_message(t('The disabled index still had active facet blocks. They were deactivated.'), 'warning', FALSE); + foreach (search_api_facet_load(array('index_id' => $id, 'enabled' => TRUE)) as $facet) { + $facet->enabled = FALSE; + $facet->save(); + } + if (isset($facet)) { + drupal_set_message(t('The disabled index still had active facet blocks. They were deactivated.'), 'status', FALSE); } } elseif ($op == 'fields') { @@ -623,11 +645,11 @@ foreach ($facets as $facet) { if (empty($fields[$facet->field]['indexed'])) { $facet->enabled = FALSE; - search_api_facet_save($facet); + $facet->save(); } elseif (empty($facet->options['type']) || $facet->options['type'] != $fields[$facet->field]['type']) { _search_api_facets_refresh_type($facet, $facet->options); - search_api_facet_save($facet); + $facet->save(); } } } @@ -640,6 +662,9 @@ db_delete('search_api_facet') ->condition('index_id', $index->machine_name) ->execute(); + if (search_api_facet_load(array('index_id' => $index->machine_name))) { + drupal_set_message(t('A module defines default search facets for the deleted index. You should update the module code or disable it.'), 'warning'); + } } /** @@ -651,7 +676,7 @@ foreach (search_api_facet_load(array('enabled' => 1)) as $facet) { if (empty($facet->options['type']) || $facet->options['type'] == 'options') { _search_api_facets_refresh_type($facet, $facet->options); - search_api_facet_save($facet); + $facet->save(); } } } @@ -670,43 +695,36 @@ * If set to TRUE, the returned facets will be freshly loaded, instead of * being loaded from the cache. * - * @return stdClass + * @return SearchApiFacet * Either the facet with the specified delta, or an array of facets matching * the specified conditions, keyed by delta. */ function search_api_facet_load($conditions = array(), $reset = FALSE) { - $cache = &drupal_static(__FUNCTION__, array()); - $key = serialize($conditions); - if (!isset($cache[$key]) || $reset) { - if (is_scalar($conditions)) { - $delta = $conditions; - $f = db_query('SELECT * FROM {search_api_facet} WHERE delta = :delta', array(':delta' => $delta))->fetch(); - if ($f) { - $f->options = $f->options ? unserialize($f->options) : array(); - } - $cache[$key] = $f; - } - else { - $select = db_select('search_api_facet', 'f'); - $select->fields('f'); - foreach ($conditions as $field => $value) { - if ($field == 'b.status') { - global $theme; - $select->join('block', 'b', 'b.module = :module AND b.delta = f.delta AND b.theme = :theme AND b.status = :status', - array(':module' => 'search_api_facets', ':theme' => $theme, ':status' => $value)); - continue; - } - $select->condition($field, $value); - } - $facets = $select->execute()->fetchAllAssoc('delta'); - foreach ($facets as $facet) { - $facet->options = $facet->options ? unserialize($facet->options) : array(); - $cache[serialize($facet->delta)] = $facet; + if (is_scalar($conditions)) { + $f = entity_load('search_api_facet', array($conditions), array(), $reset); + $f = $f ? reset($f) : FALSE; + return $f; + } + else { + $deltas = FALSE; + if (isset($conditions['b.status'])) { + $status = $conditions['b.status']; + unset($conditions['b.status']); + $cache = &drupal_static(__FUNCTION__, array()); + if (!isset($cache[$status]) || $reset) { + global $theme; + $cache[$status] = db_select('block', 'b') + ->fields('b', array('delta')) + ->condition('module', 'search_api_facets') + ->condition('theme', $theme) + ->condition('status', $status) + ->execute() + ->fetchCol(); } - $cache[$key] = $facets; + $deltas = $cache[$status]; } + return entity_load('search_api_facet', $deltas, $conditions, $reset); } - return $cache[$key]; } /** @@ -715,47 +733,11 @@ * or if $facet->is_new is set, the facet will be inserted. Otherwise, it will * be updated. * - * @param stdClass $facet + * @param SearchApiFacet $facet * The facet object to save. */ -function search_api_facet_save(stdClass $facet) { - // Always set default options. - $facet->options += array( - 'limit' => 10, - 'min_count' => 1, - 'sort' => 'count', - 'missing' => FALSE, - 'default_true' => TRUE, - 'ids_list' => array(), - 'type' => '', - ); - if (!empty($facet->delta) && empty($facet->is_new)) { - $enabled_changed = $facet->enabled != search_api_facet_load($facet->delta, TRUE)->enabled; - drupal_write_record('search_api_facet', $facet, 'delta'); - if ($enabled_changed) { - block_flush_caches(); - cache_clear_all('*', 'cache_block', TRUE); - } - return; - } - if (empty($facet->delta)) { - // Construct a delta using index id and field. - // We have to ensure that it's both unique and at most 32 characters long, - // leading to a bit of complexity. - $delta = substr($facet->index_id, 0, 20) . '_' . preg_replace('/\W+/', '_', $facet->field); - $base = $delta = substr($delta, 0, 32); - $i = 0; - while (db_query('SELECT COUNT(1) FROM {search_api_facet} WHERE delta = :delta', array(':delta' => $delta))->fetchField()) { - $suffix = '_' . ++$i; - $delta = substr($base, 0, 32 - strlen($suffix)) . $suffix; - } - $facet->delta = $delta; - } - drupal_write_record('search_api_facet', $facet); - if ($facet->enabled) { - block_flush_caches(); - cache_clear_all('*', 'cache_block', TRUE); - } +function search_api_facet_save(SearchApiFacet $facet) { + $facet->save(); } /** @@ -770,21 +752,23 @@ */ function search_api_facet_delete($conditions = array()) { if (is_scalar($conditions)) { - $delta = $conditions; - return db_delete('search_api_facet') - ->condition('delta', $delta) - ->execute() != 0; - } - $del = db_delete('search_api_facet'); - foreach ($conditions as $field => $value) { - $del->condition($field, $value); + $facet = search_api_facet_load($conditions); + if (!$facet) { + return FALSE; + } + $facet->delete(); } - if ($del->execute()) { + else { + foreach (search_api_facet_load($conditions) as $facet) { + $facet->delete(FALSE); + } + if (!isset($facet)) { + return FALSE; + } block_flush_caches(); cache_clear_all('*', 'cache_block', TRUE); - return TRUE; } - return FALSE; + return TRUE; } /** @@ -820,7 +804,7 @@ * @param array $options * An array for which 'type' and, if applicable, 'options' will be set. */ -function _search_api_facets_refresh_type(stdClass $facet, array &$options) { +function _search_api_facets_refresh_type(SearchApiFacet $facet, array &$options) { $index = search_api_index_load($facet->index_id); $type = $index->options['fields'][$facet->field]['type']; $options['type'] = search_api_extract_inner_type($type); Index: contrib/search_api_facets/search_api_facets.entity.inc =================================================================== RCS file: contrib/search_api_facets/search_api_facets.entity.inc diff -N contrib/search_api_facets/search_api_facets.entity.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ contrib/search_api_facets/search_api_facets.entity.inc 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,122 @@ +delta is empty, it will be computed automatically. In this case, + * or if $this->is_new is set, the facet will be inserted. Otherwise, it will + * be updated. + */ + public function save() { + // Always set default options. + $this->options += array( + 'limit' => 10, + 'min_count' => 1, + 'sort' => 'count', + 'missing' => FALSE, + 'default_true' => TRUE, + 'ids_list' => array(), + 'type' => '', + ); + if (!empty($this->id) && !empty($this->delta) && empty($this->is_new)) { + $enabled_changed = $this->enabled != search_api_facet_load($this->delta, TRUE)->enabled; + parent::save(); + if ($enabled_changed) { + block_flush_caches(); + cache_clear_all('*', 'cache_block', TRUE); + } + return; + } + if (empty($this->delta)) { + // Construct a delta using index id and field. + // We have to ensure that it's both unique and at most 32 characters long, + // leading to a bit of complexity. + $delta = substr($this->index_id, 0, 20) . '_' . preg_replace('/\W+/', '_', $this->field); + $base = $delta = substr($delta, 0, 32); + $i = 0; + while (search_api_facet_load($delta)) { + $suffix = '_' . ++$i; + $delta = substr($base, 0, 32 - strlen($suffix)) . $suffix; + } + $this->delta = $delta; + } + parent::save(); + if ($this->enabled) { + block_flush_caches(); + cache_clear_all('*', 'cache_block', TRUE); + } + } + + /** + * Deletes this facet. + * + * @param $flush_block_caches + * TRUE, if the block caches should be flushed after deleting the facet. + */ + public function delete($flush_block_caches = TRUE) { + parent::delete(); + if ($flush_block_caches) { + block_flush_caches(); + cache_clear_all('*', 'cache_block', TRUE); + } + } + +}