From 355363b46fdf99364027fffac2801d7242242703 Mon Sep 17 00:00:00 2001 From: nickw Date: Wed, 21 Oct 2009 16:11:26 +0000 Subject: Allowing entities to be retrieved by case-insensitive search. Adding a new unit test for ElggMetadata. git-svn-id: http://code.elgg.org/elgg/trunk@3568 36083f99-b078-4883-b0ff-0f9b5a30f544 --- engine/lib/metadata.php | 40 +++++++++++++---- engine/lib/metastrings.php | 73 +++++++++++++++++++------------ engine/tests/objects/metadata.php | 92 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 35 deletions(-) create mode 100644 engine/tests/objects/metadata.php diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 5ca39b586..dc8107583 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -544,17 +544,24 @@ function find_metadata($meta_name = "", $meta_value = "", $entity_type = "", $en * @param string $order_by Optional ordering. * @param int $site_guid The site to get entities for. Leave as 0 (default) for the current site; -1 for all sites. * @param true|false $count If set to true, returns the total number of entities rather than a list. (Default: false) + * @param true|false $case_sensitive If set to false this searches for the meta data without case sensitivity. (Default: true) * * @return int|array A list of entities, or a count if $count is set to true */ -function get_entities_from_metadata($meta_name, $meta_value = "", $entity_type = "", $entity_subtype = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "", $site_guid = 0, $count = false) { +function get_entities_from_metadata($meta_name, $meta_value = "", $entity_type = "", $entity_subtype = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "", $site_guid = 0, $count = FALSE, $case_sensitive = TRUE) { global $CONFIG; $meta_n = get_metastring_id($meta_name); - $meta_v = get_metastring_id($meta_value); + $meta_v = get_metastring_id($meta_value, $case_sensitive); $entity_type = sanitise_string($entity_type); - $entity_subtype = get_subtype_id($entity_type, $entity_subtype); + $entity_subtype_id = get_subtype_id($entity_type, $entity_subtype); + if ($entity_subtype != "" && $entity_subtype_id == FALSE) { + return false; + } else { + $entity_subtype = $entity_subtype_id; + } + $limit = (int)$limit; $offset = (int)$offset; if ($order_by == "") { @@ -590,7 +597,16 @@ function get_entities_from_metadata($meta_name, $meta_value = "", $entity_type = $where[] = "m.name_id='$meta_n'"; } if ($meta_value!=="") { - $where[] = "m.value_id='$meta_v'"; + if (is_array($meta_v)) { + $meta_v_string = ""; + foreach ($meta_v as $v) { + $meta_v_string .= "'$v',"; + } + $meta_v_string = rtrim($meta_v_string, ","); + $where[] = "m.value_id in ($meta_v_string)"; + } else { + $where[] = "m.value_id='$meta_v'"; + } } if ($site_guid > 0) { $where[] = "e.site_guid = {$site_guid}"; @@ -641,11 +657,11 @@ function get_entities_from_metadata($meta_name, $meta_value = "", $entity_type = * * @return string A list of entities suitable for display */ -function list_entities_from_metadata($meta_name, $meta_value = "", $entity_type = "", $entity_subtype = "", $owner_guid = 0, $limit = 10, $fullview = true, $viewtypetoggle = true, $pagination = true) { +function list_entities_from_metadata($meta_name, $meta_value = "", $entity_type = "", $entity_subtype = "", $owner_guid = 0, $limit = 10, $fullview = true, $viewtypetoggle = true, $pagination = true, $case_sensitive = true ) { $offset = (int) get_input('offset'); $limit = (int) $limit; - $count = get_entities_from_metadata($meta_name, $meta_value, $entity_type, $entity_subtype, $owner_guid, $limit, $offset, "", 0, true); - $entities = get_entities_from_metadata($meta_name, $meta_value, $entity_type, $entity_subtype, $owner_guid, $limit, $offset, "", 0, false); + $count = get_entities_from_metadata($meta_name, $meta_value, $entity_type, $entity_subtype, $owner_guid, $limit, $offset, "", 0, true, $case_sensitive ); + $entities = get_entities_from_metadata($meta_name, $meta_value, $entity_type, $entity_subtype, $owner_guid, $limit, $offset, "", 0, false, $case_sensitive ); return elgg_view_entity_list($entities, $count, $offset, $limit, $fullview, $viewtypetoggle, $pagination); } @@ -972,4 +988,12 @@ function register_metadata_url_handler($function_name, $extender_name = "all") { /** Register the hook */ register_plugin_hook("export", "all", "export_metadata_plugin_hook", 2); /** Call a function whenever an entity is updated **/ -register_elgg_event_handler('update','all','metadata_update'); \ No newline at end of file +register_elgg_event_handler('update','all','metadata_update'); + +// unit testing +register_plugin_hook('unit_test', 'system', 'metadata_test'); +function metadata_test($hook, $type, $value, $params) { + global $CONFIG; + $value[] = $CONFIG->path . 'engine/tests/objects/metadata.php'; + return $value; +} \ No newline at end of file diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index 3e8796d3f..a2f95b9f8 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -19,44 +19,63 @@ $METASTRINGS_DEADNAME_CACHE = array(); * Return the meta string id for a given tag, or false. * * @param string $string The value (whatever that is) to be stored - * @param bool $case_sensitive Do we want to make the query case sensitive? - * @return mixed Integer tag or false. + * @param bool $case_sensitive Do we want to make the query case sensitive? If not there may be more than one result + * @return int|array|false meta string id, array of ids or false if none found */ -function get_metastring_id($string, $case_sensitive = true) { +function get_metastring_id($string, $case_sensitive = TRUE) { global $CONFIG, $METASTRINGS_CACHE, $METASTRINGS_DEADNAME_CACHE; $string = sanitise_string($string); - $result = array_search($string, $METASTRINGS_CACHE); - if ($result!==false) { - elgg_log("** Returning id for string:$string from cache."); - return $result; - } - - // See if we have previously looked for this and found nothing - if (in_array($string, $METASTRINGS_DEADNAME_CACHE)) { - return false; - } + + // caching doesn't work for case insensitive searches + if ($case_sensitive) { + $result = array_search($string, $METASTRINGS_CACHE); + + if ($result!==false) { + elgg_log("** Returning id for string:$string from cache."); + return $result; + } - // Experimental memcache - $msfc = null; - static $metastrings_memcache; - if ((!$metastrings_memcache) && (is_memcache_available())) { - $metastrings_memcache = new ElggMemcache('metastrings_memcache'); - } - if ($metastrings_memcache) { - $msfc = $metastrings_memcache->load($string); - } - if ($msfc) { - return $msfc; + // See if we have previously looked for this and found nothing + if (in_array($string, $METASTRINGS_DEADNAME_CACHE)) { + return false; + } + + // Experimental memcache + $msfc = null; + static $metastrings_memcache; + if ((!$metastrings_memcache) && (is_memcache_available())) { + $metastrings_memcache = new ElggMemcache('metastrings_memcache'); + } + if ($metastrings_memcache) { + $msfc = $metastrings_memcache->load($string); + } + if ($msfc) { + return $msfc; + } } // Case sensitive - $cs = ""; if ($case_sensitive) { - $cs = " BINARY "; + $query = "SELECT * from {$CONFIG->dbprefix}metastrings where string= BINARY '$string' limit 1"; + } else { + $query = "SELECT * from {$CONFIG->dbprefix}metastrings where strcmp(string,'$string')=0"; } - $row = get_data_row("SELECT * from {$CONFIG->dbprefix}metastrings where string=$cs'$string' limit 1"); + $row = FALSE; + $metaStrings = get_data($query, "entity_row_to_elggstar"); + if (is_array($metaStrings)) { + if (sizeof($metaStrings) > 1) { + $ids = array(); + foreach($metaStrings as $metaString) { + $ids[] = $metaString->id; + } + return $ids; + } else { + $row = $metaStrings[0]; + } + } + if ($row) { $METASTRINGS_CACHE[$row->id] = $row->string; // Cache it diff --git a/engine/tests/objects/metadata.php b/engine/tests/objects/metadata.php new file mode 100644 index 000000000..eb635db4a --- /dev/null +++ b/engine/tests/objects/metadata.php @@ -0,0 +1,92 @@ +metastrings = array(); + $this->object = new ElggObject(); + } + + /** + * Called after each test method. + */ + public function tearDown() { + // do not allow SimpleTest to interpret Elgg notices as exceptions + $this->swallowErrors(); + + unset($this->object); + } + + public function testGetMetastringById() { + foreach (array('metaUnitTest', 'metaunittest', 'METAUNITTEST') as $string) { + $this->create_metastring($string); + } + + // lookup metastring id + $cs_ids = get_metastring_id('metaUnitTest', TRUE); + $this->assertEqual($cs_ids, $this->metastrings['metaUnitTest']); + + // lookup all metastrings, ignoring case + $cs_ids = get_metastring_id('metaUnitTest', FALSE); + $this->assertEqual(count($cs_ids), 3); + $this->assertEqual(count($cs_ids), count($this->metastrings)); + foreach ($cs_ids as $string ) + { + $this->assertTrue(in_array($string, $this->metastrings)); + } + + // clean up + $this->delete_metastrings(); + } + + public function testGetEntitiesFromMetadata() { + $this->object->title = 'Meta Unit Test'; + $this->object->save(); + $this->create_metastring('metaUnitTest'); + $this->create_metastring('tested'); + $this->assertTrue(create_metadata($this->object->guid, 'metaUnitTest', 'tested')); + + // check value with improper case + $this->assertFalse(get_entities_from_metadata('metaUnitTest', 'Tested', '', '', 0, 10, 0, '', 0, FALSE, TRUE)); + + // compare forced case with ignored case + $case_true = get_entities_from_metadata('metaUnitTest', 'tested', '', '', 0, 10, 0, '', 0, FALSE, TRUE); + $case_false = get_entities_from_metadata('metaUnitTest', 'Tested', '', '', 0, 10, 0, '', 0, FALSE, FALSE); + $this->assertIsA($case_true, 'array'); + $this->assertIsA($case_false, 'array'); + $this->assertIdentical($case_true, $case_false); + + // check entity list + //$this->dump(list_entities_from_metadata('metaUnitTest', 'Tested', '', '', 0, 10, TRUE, TRUE, TRUE, FALSE)); + + // clean up + $this->delete_metastrings(); + $this->object->delete(); + } + + + protected function create_metastring($string) { + global $CONFIG; + + mysql_query("INSERT INTO {$CONFIG->dbprefix}metastrings (string) VALUES ('$string')"); + $this->metastrings[$string] = mysql_insert_id(); + } + + protected function delete_metastrings() { + global $CONFIG; + + $strings = implode(', ', $this->metastrings); + mysql_query("DELETE FROM {$CONFIG->dbprefix}metastrings WHERE id IN ($strings)"); + } +} -- cgit v1.2.3