diff options
-rw-r--r-- | CODING.txt | 62 | ||||
-rw-r--r-- | INSTALL.txt | 2 | ||||
-rw-r--r-- | engine/lib/elgglib.php | 17 | ||||
-rw-r--r-- | engine/lib/metadata.php | 24 | ||||
-rw-r--r-- | engine/lib/output.php | 2 | ||||
-rw-r--r-- | engine/lib/relationships.php | 5 | ||||
-rw-r--r-- | engine/lib/upgrades/2010062301.php | 21 | ||||
-rw-r--r-- | engine/lib/upgrades/2010062302.php | 33 | ||||
-rw-r--r-- | engine/schema/mysql.sql | 1 | ||||
-rw-r--r-- | engine/schema/upgrades/2010062401.sql | 1 | ||||
-rw-r--r-- | engine/tests/api/entity_getter_functions.php | 189 | ||||
-rw-r--r-- | mod/groups/languages/en.php | 2 | ||||
-rw-r--r-- | mod/groups/start.php | 22 | ||||
-rw-r--r-- | mod/groups/views/default/groups/grouplisting.php | 2 | ||||
-rw-r--r-- | mod/search/search_hooks.php | 76 | ||||
-rw-r--r-- | mod/search/start.php | 40 | ||||
-rw-r--r-- | version.php | 2 | ||||
-rw-r--r-- | views/default/friends/picker.php | 8 | ||||
-rw-r--r-- | views/default/input/checkboxes.php | 109 |
19 files changed, 480 insertions, 138 deletions
diff --git a/CODING.txt b/CODING.txt index b2224627f..3399d8e2f 100644 --- a/CODING.txt +++ b/CODING.txt @@ -3,11 +3,15 @@ These are the coding standards for Elgg. All core development, bundled plugins, and tickets attached to Trac are expected to be in this format. -* Unix line endings +* Unix line endings. + * Hard tabs, 4 character tab spacing. -* No PHP shortcut tags ( <? or <?= or <% ) + +* No PHP shortcut tags ( <? or <?= or <% ). + * PHPDoc comments on functions and classes (all methods; declared properties when appropriate). + * Mandatory wrapped {}s around any code blocks. Bad: if (true) @@ -20,22 +24,32 @@ plugins, and tickets attached to Trac are expected to be in this format. echo $elem; } } + * Name standalone functions using underscore_character(). + * Name classes using CamelCase() and methods using lowerCamelCase(). -* Name globals and constants in ALL_CAPS (FALSE, TRUE, NULL, ACCESS_FRIENDS, - $CONFIG). -* Space functions like_this($required, $optional = TRUE) -* Space keywords and constructs like this: if (FALSE) { ... } + +* Name globals and constants in ALL_CAPS (TRUE, NULL, ACCESS_FRIENDS, $CONFIG). + +* Use underscores / camel case to separate standard English words in + functions, classes, and methods. (get_default_site(), ElggUser->isLoggedIn()). + +* Space functions like_this($required, $optional = TRUE). + +* Space keywords and constructs like this: if (FALSE) { ... }. + * Correctly use spaces, quotes, and {}s in strings: Bad (hard to read, misuse of quotes and {}s): echo 'Hello, '.$name."! How is your {$time_of_day}?"; Good: echo "Hello, $name! How is your $time_of_day?"; - + * Line lengths should be reasonable. If you are writing lines over 100 characters on a line, please revise the code. + * Use // or /* */ when commenting. + * No closing PHP tag (?>) at EOF unless after a heredoc. (Avoids problems with trailing whitespace. Required after heredoc by PHP.) @@ -51,18 +65,25 @@ work for developers, which means happier, more productive developers. If you find a block of code that you want to use multiple times, make a function. If you find views that are identical except for a single value, pull it out into a generic view that takes an option. + * Whitespace is free. Don't be afraid to use it to separate blocks of code. Use a single space to separate function params and string concatenation. + * Use self-documenting variable names. $group_guids is better than $array. + * Functions returning an array should return an empty array instead of FALSE on no results. -* FALSE should be returned by functions on failure or error if not throwing an - exception. + +* Functions not throwing an exception on error should return FALSE upon + failure. + * Functions returning only boolean should be prefaced with is_ or has_ (eg, is_logged_in(), has_access_to_entity()). + * Ternary syntax is acceptable for single-line, non-embedded statements. + * Use comments effectively. Good comments describe the "why." Good code - describes the "how." Ex: + describes the "how." Ex: Not a very useful comment: // increment $i only when the entity is marked as active. @@ -80,13 +101,14 @@ work for developers, which means happier, more productive developers. $i++; } } + * Use commit messages effectively. Be concise and meaningful. Ex: Not meaningful: Small fix to groups. Meaningful: - Fixes #1234: Missing ) was causing WSOD on group profile page when - logged out. + Fixes #1234: Added missing ) that caused a WSOD on group profile page + when logged out. * Commit effectively: Err on the side of atomic commits. One revision with many changes is scary. @@ -101,24 +123,30 @@ indefinitely as plugin authors are expected to properly update their plugins. In order to maintain backward compatibility, deprecated APIs will follow these guidelines: -* API changes cannot occur between bugfix versions (1.6.0 - 1.6.1). +* Incompatible API changes cannot occur between bugfix versions + (1.6.0 - 1.6.1). + * API changes between minor versions (1.6 - 1.7) must maintain backward compatibility for at least 2 minor versions. (1.7 and 1.8. See procedures, below.) + * Bugfixes that change the API cannot be included in bugfix versions. + * API changes between major versions (1.0 - 2.0) can occur without regard to backward compatibility. -The procedures for deprecating an API are as follows: +The procedure for deprecating an API is as follows: * The first minor version (1.7) with a deprecated API must include a wrapper function/class (or otherwise appropriate means) to maintain backward compatibility, including any bugs in the original function/class. - This wrapper function will elgg_deprecated_notice('...', 1.7) to log + This compatibility layer uses elgg_deprecated_notice('...', 1.7) to log that the function is deprecated. + * The second minor version (1.8) maintains the backward compatibility - wrapper, but elgg_deprecated_notice() will produce a visible warning. -* The third minor version (1.9) removes the wrapper function. Any use of + layer, but elgg_deprecated_notice() will produce a visible warning. + +* The third minor version (1.9) removes the compatibility layer. Any use of the deprecated API should be corrected before this. The general timeline for two minor releases is 8 to 12 months. diff --git a/INSTALL.txt b/INSTALL.txt index 20007fad7..33aa23708 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -66,7 +66,7 @@ Once this folder has been created, you'll need to make sure that your web server has permission to write to it. This shouldn't be a problem on Windows-based servers, but if your server runs Linux or a UNIX variant, you'll need to figure out what user Apache runs under. For Debian-based -distros, it is usually www-data and for RedHat, it is often apache. If +distros, it is usually www-data and for RedHat, it is often apache. If you cannot figure out what the ownership and permissions should be, you can set the permissions for world access (though not recommended): diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index f74fbec09..3d08227e4 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -1624,22 +1624,15 @@ function is_not_null($string) { function elgg_normalise_plural_options_array($options, $singulars) { foreach ($singulars as $singular) { $plural = $singular . 's'; - - // normalize the singular to plural - // isset() returns FALSE for array values of NULL, so they are ignored. - // everything else falsy is included. - //if (isset($options[$singular]) && $options[$singular] !== NULL && $options[$singular] !== FALSE) { - if (isset($options[$singular])) { - if (isset($options[$plural])) { - if (is_array($options[$plural])) { - $options[$plural][] = $options[$singlar]; - } else { - $options[$plural] = array($options[$plural], $options[$singular]); - } + + if (array_key_exists($singular, $options)) { + if ($options[$singular] === ELGG_ENTITIES_ANY_VALUE) { + $options[$plural] = $options[$singular]; } else { $options[$plural] = array($options[$singular]); } } + unset($options[$singular]); } diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 74ea6858a..6e849cdd9 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -186,10 +186,11 @@ function remove_metadata($entity_guid, $name, $value = "") { * @param int $entity_guid The entity to attach the metadata to * @param string $name Name of the metadata * @param string $value Value of the metadata (cannot be associative array) - * @param string $value_type - * @param int $owner_guid - * @param int $access_id - * @param bool $allow_multiple + * @param string $value_type 'text', 'integer', or '' for automatic detection + * @param int $owner_guid GUID of entity that owns the metadata + * @param int $access_id Default is ACCESS_PRIVATE + * @param bool $allow_multiple Allow multiple values for one key. Default is FALSE + * @return bool */ function create_metadata($entity_guid, $name, $value, $value_type, $owner_guid, $access_id = ACCESS_PRIVATE, $allow_multiple = false) { global $CONFIG; @@ -218,8 +219,7 @@ function create_metadata($entity_guid, $name, $value, $value_type, $owner_guid, if (!$result) { return false; } - } - else if (isset($value)) { + } else if (isset($value)) { // Support boolean types if (is_bool($value)) { if ($value) { @@ -343,12 +343,12 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i /** * This function creates metadata from an associative array of "key => value" pairs. * - * @param int $entity_guid - * @param string $name_and_values - * @param string $value_type - * @param int $owner_guid - * @param int $access_id - * @param bool $allow_multiple + * @param int $entity_guid The entity to attach the metadata to + * @param string $name_and_values Associative array + * @param string $value_type 'text', 'integer', or '' for automatic detection + * @param int $owner_guid GUID of entity that owns the metadata + * @param int $access_id Default is ACCESS_PRIVATE + * @param bool $allow_multiple Allow multiple values for one key. Default is FALSE */ function create_metadata_from_array($entity_guid, array $name_and_values, $value_type, $owner_guid, $access_id = ACCESS_PRIVATE, $allow_multiple = false) { foreach ($name_and_values as $k => $v) { diff --git a/engine/lib/output.php b/engine/lib/output.php index 70c3821d6..3b82447b0 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -116,7 +116,7 @@ function elgg_make_excerpt($text, $num_chars = 250) { $excerpt = trim(elgg_substr($excerpt, 0, $space)); if ($string_length != elgg_strlen($excerpt)) { - $excerpt .= '…'; + $excerpt .= '...'; } return $excerpt; diff --git a/engine/lib/relationships.php b/engine/lib/relationships.php index f813cacba..f1d119452 100644 --- a/engine/lib/relationships.php +++ b/engine/lib/relationships.php @@ -358,13 +358,16 @@ function add_entity_relationship($guid_one, $relationship, $guid_two) { $guid_one = (int)$guid_one; $relationship = sanitise_string($relationship); $guid_two = (int)$guid_two; + $time = time(); // Check for duplicates if (check_entity_relationship($guid_one, $relationship, $guid_two)) { return false; } - $result = insert_data("INSERT into {$CONFIG->dbprefix}entity_relationships (guid_one, relationship, guid_two) values ($guid_one, '$relationship', $guid_two)"); + $result = insert_data("INSERT into {$CONFIG->dbprefix}entity_relationships + (guid_one, relationship, guid_two, time_created) + values ($guid_one, '$relationship', $guid_two, $time)"); if ($result!==false) { $obj = get_relationship($result); diff --git a/engine/lib/upgrades/2010062301.php b/engine/lib/upgrades/2010062301.php new file mode 100644 index 000000000..96fd6c810 --- /dev/null +++ b/engine/lib/upgrades/2010062301.php @@ -0,0 +1,21 @@ +<?php + +/** + * Change ownership of group ACLs to group entity + */ + +elgg_set_ignore_access(TRUE); + +$params = array('type' => 'group', + 'limit' => 0); +$groups = elgg_get_entities($params); +if ($groups) { + foreach ($groups as $group) { + $acl = $group->group_acl; + + $query = "UPDATE {$CONFIG->dbprefix}access_collections SET owner_guid = $group->guid WHERE id = $acl"; + update_data($query); + } +} +elgg_set_ignore_access(FALSE); + diff --git a/engine/lib/upgrades/2010062302.php b/engine/lib/upgrades/2010062302.php new file mode 100644 index 000000000..fe33e12ea --- /dev/null +++ b/engine/lib/upgrades/2010062302.php @@ -0,0 +1,33 @@ +<?php + +/** + * Make sure that everyone who belongs to a group is a member of the group's access collection + */ + + +elgg_set_ignore_access(TRUE); + +$params = array('type' => 'group', 'limit' => 0); +$groups = elgg_get_entities($params); +if ($groups) { + foreach ($groups as $group) { + $acl = $group->group_acl; + + $query = "SELECT u.guid FROM {$CONFIG->dbprefix}users_entity u + JOIN {$CONFIG->dbprefix}entity_relationships r + ON u.guid = r.guid_one AND r.relationship = 'member' AND r.guid_two = $group->guid + LEFT JOIN {$CONFIG->dbprefix}access_collection_membership a + ON u.guid = a.user_guid AND a.access_collection_id = $acl + WHERE a.user_guid IS NULL"; + + $results = get_data($query); + if ($results != FALSE) { + foreach ($results as $user) { + $insert = "INSERT INTO {$CONFIG->dbprefix}access_collection_membership + (user_guid, access_collection_id) VALUES ($user->guid, $acl)"; + insert_data($insert); + } + } + } +} +elgg_set_ignore_access(FALSE); diff --git a/engine/schema/mysql.sql b/engine/schema/mysql.sql index 23e81f39d..526cc8ce6 100644 --- a/engine/schema/mysql.sql +++ b/engine/schema/mysql.sql @@ -155,6 +155,7 @@ CREATE TABLE `prefix_entity_relationships` ( `guid_one` bigint(20) unsigned NOT NULL, `relationship` varchar(50) NOT NULL, `guid_two` bigint(20) unsigned NOT NULL, + `time_created` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `guid_one` (`guid_one`,`relationship`,`guid_two`), KEY `relationship` (`relationship`), diff --git a/engine/schema/upgrades/2010062401.sql b/engine/schema/upgrades/2010062401.sql new file mode 100644 index 000000000..fbb49bfcf --- /dev/null +++ b/engine/schema/upgrades/2010062401.sql @@ -0,0 +1 @@ +ALTER TABLE `prefix_entity_relationships` ADD COLUMN `time_created` int(11) NOT NULL AFTER `guid_two`;
\ No newline at end of file diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index faa91db34..f193fda41 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2168,7 +2168,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { ); $es = elgg_get_entities_from_relationship($options); - + $this->assertTrue(empty($es)); foreach ($guids as $guid) { @@ -2176,4 +2176,191 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { $e->delete(); } } + + public function testElggApiGettersEntitySiteSingular() { + global $CONFIG; + + $guids = array(); + + $obj1 = new ElggObject(); + $obj1->test_md = 'test'; + // luckily this is never checked. + $obj1->site_guid = 2; + $obj1->save(); + $guids[] = $obj1->guid; + $right_guid = $obj1->guid; + + $obj2 = new ElggObject(); + $obj2->test_md = 'test'; + $obj2->site_guid = $CONFIG->site->guid; + $obj2->save(); + $guids[] = $obj2->guid; + + $options = array( + 'metadata_name' => 'test_md', + 'metadata_value' => 'test', + 'site_guid' => 2 + ); + + $es = elgg_get_entities_from_metadata($options); + $this->assertTrue(is_array($es)); + $this->assertEqual(1, count($es)); + $this->assertEqual($right_guid, $es[0]->guid); + + foreach ($guids as $guid) { + get_entity($guid)->delete(); + } + } + + public function testElggApiGettersEntitySiteSingularAny() { + global $CONFIG; + + $guids = array(); + + $obj1 = new ElggObject(); + $obj1->test_md = 'test'; + // luckily this is never checked. + $obj1->site_guid = 2; + $obj1->save(); + $guids[] = $obj1->guid; + + $obj2 = new ElggObject(); + $obj2->test_md = 'test'; + $obj2->site_guid = $CONFIG->site->guid; + $obj2->save(); + $guids[] = $obj2->guid; + + $options = array( + 'metadata_name' => 'test_md', + 'metadata_value' => 'test', + 'site_guid' => ELGG_ENTITIES_ANY_VALUE, + 'limit' => 2, + 'order_by' => 'e.guid DESC' + ); + + $es = elgg_get_entities_from_metadata($options); + $this->assertTrue(is_array($es)); + $this->assertEqual(2, count($es)); + + foreach ($es as $e) { + $this->assertTrue(in_array($e->guid, $guids)); + } + + foreach ($guids as $guid) { + get_entity($guid)->delete(); + } + } + + public function testElggApiGettersEntitySitePlural() { + global $CONFIG; + + $guids = array(); + + $obj1 = new ElggObject(); + $obj1->test_md = 'test'; + // luckily this is never checked. + $obj1->site_guid = 2; + $obj1->save(); + $guids[] = $obj1->guid; + + $obj2 = new ElggObject(); + $obj2->test_md = 'test'; + $obj2->site_guid = $CONFIG->site->guid; + $obj2->save(); + $guids[] = $obj2->guid; + + $options = array( + 'metadata_name' => 'test_md', + 'metadata_value' => 'test', + 'site_guids' => array($CONFIG->site->guid, 2), + 'limit' => 2, + 'order_by' => 'e.guid DESC' + ); + + $es = elgg_get_entities_from_metadata($options); + $this->assertTrue(is_array($es)); + $this->assertEqual(2, count($es)); + + foreach ($es as $e) { + $this->assertTrue(in_array($e->guid, $guids)); + } + + foreach ($guids as $guid) { + get_entity($guid)->delete(); + } + } + + public function testElggApiGettersEntitySitePluralSomeInvalid() { + global $CONFIG; + + $guids = array(); + + $obj1 = new ElggObject(); + $obj1->test_md = 'test'; + // luckily this is never checked. + $obj1->site_guid = 2; + $obj1->save(); + $guids[] = $obj1->guid; + + $obj2 = new ElggObject(); + $obj2->test_md = 'test'; + $obj2->save(); + $guids[] = $obj2->guid; + $right_guid = $obj2->guid; + + $options = array( + 'metadata_name' => 'test_md', + 'metadata_value' => 'test', + // just created the first entity so nothing will be "sited" by it. + 'site_guids' => array($CONFIG->site->guid, $guids[0]), + 'limit' => 2, + 'order_by' => 'e.guid DESC' + ); + + $es = elgg_get_entities_from_metadata($options); + + $this->assertTrue(is_array($es)); + $this->assertEqual(1, count($es)); + $this->assertEqual($es[0]->guid, $right_guid); + + foreach ($guids as $guid) { + get_entity($guid)->delete(); + } + } + + public function testElggApiGettersEntitySitePluralAllInvalid() { + global $CONFIG; + + $guids = array(); + + $obj1 = new ElggObject(); + $obj1->test_md = 'test'; + // luckily this is never checked. + $obj1->site_guid = 2; + $obj1->save(); + $guids[] = $obj1->guid; + + $obj2 = new ElggObject(); + $obj2->test_md = 'test'; + $obj2->save(); + $guids[] = $obj2->guid; + $right_guid = $obj2->guid; + + $options = array( + 'metadata_name' => 'test_md', + 'metadata_value' => 'test', + // just created the first entity so nothing will be "sited" by it. + 'site_guids' => array($guids[0], $guids[1]), + 'limit' => 2, + 'order_by' => 'e.guid DESC' + ); + + $es = elgg_get_entities_from_metadata($options); + + $this->assertTrue(empty($es)); + + foreach ($guids as $guid) { + get_entity($guid)->delete(); + } + } } diff --git a/mod/groups/languages/en.php b/mod/groups/languages/en.php index 58a6c7f31..7ecd00f57 100644 --- a/mod/groups/languages/en.php +++ b/mod/groups/languages/en.php @@ -133,7 +133,7 @@ $english = array( 'grouptopic:error' => 'Your group topic could not be created. Please try again or contact a system administrator.', 'groups:forumpost:edited' => "You have successfully edited the forum post.", 'groups:forumpost:error' => "There was a problem editing the forum post.", - 'groups:privategroup' => 'This group is private, requesting membership.', + 'groups:privategroup' => 'This group is closed. Requesting membership.', 'groups:notitle' => 'Groups must have a title', 'groups:cantjoin' => 'Can not join group', 'groups:cantleave' => 'Could not leave group', diff --git a/mod/groups/start.php b/mod/groups/start.php index 3278b6682..215311ef9 100644 --- a/mod/groups/start.php +++ b/mod/groups/start.php @@ -356,20 +356,18 @@ } /** - * Groups created, so add users to access lists. + * Groups created so create an access list for it */ function groups_create_event_listener($event, $object_type, $object) { - //if (($event == 'create') && ($object_type == 'group') && ($object instanceof ElggGroup)) - //{ - $group_id = create_access_collection(elgg_echo('groups:group') . ": " . $object->name); - if ($group_id) - { - $object->group_acl = $group_id; - } - else - return false; - //} + $ac_name = elgg_echo('groups:group') . ": " . $object->name; + $group_id = create_access_collection($ac_name, $object->guid); + if ($group_id) { + $object->group_acl = $group_id; + } else { + // delete group if access creation fails + return false; + } return true; } @@ -459,7 +457,6 @@ add_user_to_access_collection($user->guid, $acl); return true; - } /** @@ -475,7 +472,6 @@ remove_user_from_access_collection($user->guid, $acl); return true; - } /** diff --git a/mod/groups/views/default/groups/grouplisting.php b/mod/groups/views/default/groups/grouplisting.php index 48a7b1ace..687aebfa0 100644 --- a/mod/groups/views/default/groups/grouplisting.php +++ b/mod/groups/views/default/groups/grouplisting.php @@ -19,7 +19,7 @@ $icon = elgg_view( //get the membership type $membership = $vars['entity']->membership; -if($membership == 2) { +if($membership == ACCESS_PUBLIC) { $mem = elgg_echo("groups:open"); } else { $mem = elgg_echo("groups:closed"); diff --git a/mod/search/search_hooks.php b/mod/search/search_hooks.php index 86a6b452f..516bb2098 100644 --- a/mod/search/search_hooks.php +++ b/mod/search/search_hooks.php @@ -24,18 +24,19 @@ function search_objects_hook($hook, $type, $value, $params) { $params['joins'] = array($join); $fields = array('title', 'description'); - $where = search_get_where_sql('oe', $fields, $params); + $where = search_get_where_sql('oe', $fields, $params, FALSE); $params['wheres'] = array($where); - - $entities = elgg_get_entities($params); $params['count'] = TRUE; $count = elgg_get_entities($params); - + // no need to continue if nothing here. if (!$count) { return array('entities' => array(), 'count' => $count); } + + $params['count'] = FALSE; + $entities = elgg_get_entities($params); // add the volatile data for why these entities have been returned. foreach ($entities as $entity) { @@ -68,25 +69,28 @@ function search_groups_hook($hook, $type, $value, $params) { $join = "JOIN {$CONFIG->dbprefix}groups_entity ge ON e.guid = ge.guid"; $params['joins'] = array($join); + + $fields = array('name', 'description'); + + // force into boolean mode because we've having problems with the + // "if > 50% match 0 sets are returns" problem. + $where = search_get_where_sql('ge', $fields, $params, FALSE); - $where = "(ge.guid = e.guid - AND (ge.name LIKE '%$query%' - OR ge.description LIKE '%$query%' - ) - )"; $params['wheres'] = array($where); // override subtype -- All groups should be returned regardless of subtype. $params['subtype'] = ELGG_ENTITIES_ANY_VALUE; - $entities = elgg_get_entities($params); $params['count'] = TRUE; $count = elgg_get_entities($params); - + // no need to continue if nothing here. if (!$count) { return array('entities' => array(), 'count' => $count); } + + $params['count'] = FALSE; + $entities = elgg_get_entities($params); // add the volatile data for why these entities have been returned. foreach ($entities as $entity) { @@ -122,17 +126,20 @@ function search_users_hook($hook, $type, $value, $params) { $join = "JOIN {$CONFIG->dbprefix}users_entity ue ON e.guid = ue.guid"; $params['joins'] = array($join); - $where = "(ue.guid = e.guid - AND (ue.username LIKE '%$query%' - OR ue.name LIKE '%$query%' - ) - )"; +// $where = "(ue.guid = e.guid +// AND (ue.username LIKE '%$query%' +// OR ue.name LIKE '%$query%' +// ) +// )"; + + $fields = array('username', 'name'); + $where = search_get_where_sql('ue', $fields, $params, FALSE); + $params['wheres'] = array($where); // override subtype -- All users should be returned regardless of subtype. $params['subtype'] = ELGG_ENTITIES_ANY_VALUE; - $entities = elgg_get_entities($params); $params['count'] = TRUE; $count = elgg_get_entities($params); @@ -140,6 +147,9 @@ function search_users_hook($hook, $type, $value, $params) { if (!$count) { return array('entities' => array(), 'count' => $count); } + + $params['count'] = FALSE; + $entities = elgg_get_entities($params); // add the volatile data for why these entities have been returned. foreach ($entities as $entity) { @@ -212,7 +222,6 @@ function search_tags_hook($hook, $type, $value, $params) { $params['wheres'][] = "(msn.string IN ($tags_in) AND msv.string = '$query' AND $access)"; - $entities = elgg_get_entities($params); $params['count'] = TRUE; $count = elgg_get_entities($params); @@ -220,6 +229,9 @@ function search_tags_hook($hook, $type, $value, $params) { if (!$count) { return array('entities' => array(), 'count' => $count); } + + $params['count'] = FALSE; + $entities = elgg_get_entities($params); // add the volatile data for why these entities have been returned. foreach ($entities as $entity) { @@ -332,7 +344,7 @@ function search_comments_hook($hook, $type, $value, $params) { $e_access = get_access_sql_suffix('e'); $a_access = get_access_sql_suffix('a'); // @todo this can probably be done through the api.. - $q = "SELECT DISTINCT a.*, msv.string as comment FROM {$CONFIG->dbprefix}annotations a + $q = "SELECT count(DISTINCT a.id) as total FROM {$CONFIG->dbprefix}annotations a JOIN {$CONFIG->dbprefix}metastrings msn ON a.name_id = msn.id JOIN {$CONFIG->dbprefix}metastrings msv ON a.value_id = msv.id JOIN {$CONFIG->dbprefix}entities e ON a.entity_guid = e.guid @@ -341,13 +353,20 @@ function search_comments_hook($hook, $type, $value, $params) { AND $e_access AND $a_access $container_and - - LIMIT {$params['offset']}, {$params['limit']} "; - $comments = get_data($q); - - $q = "SELECT count(DISTINCT a.id) as total FROM {$CONFIG->dbprefix}annotations a + if (!$result = get_data($q)) { + return FALSE; + } + + $count = $result[0]->total; + + // don't continue if nothing there... + if (!$count) { + return array ('entities' => array(), 'count' => 0); + } + + $q = "SELECT DISTINCT a.*, msv.string as comment FROM {$CONFIG->dbprefix}annotations a JOIN {$CONFIG->dbprefix}metastrings msn ON a.name_id = msn.id JOIN {$CONFIG->dbprefix}metastrings msv ON a.value_id = msv.id JOIN {$CONFIG->dbprefix}entities e ON a.entity_guid = e.guid @@ -356,14 +375,11 @@ function search_comments_hook($hook, $type, $value, $params) { AND $e_access AND $a_access $container_and - "; - $result = get_data($q); - $count = $result[0]->total; + LIMIT {$params['offset']}, {$params['limit']} + "; - if (!is_array($comments)) { - return FALSE; - } + $comments = get_data($q); // @todo if plugins are disabled causing subtypes // to be invalid and there are comments on entities of those subtypes, diff --git a/mod/search/start.php b/mod/search/start.php index 781afb8ec..ae5e71c97 100644 --- a/mod/search/start.php +++ b/mod/search/start.php @@ -259,8 +259,12 @@ function search_highlight_words($words, $string) { ); foreach ($words as $word) { + // remove any boolean mode operators + $word = preg_replace("/([\-\+~])([\w]+)/i", '$2', $word); + // escape the delimiter and any other regexp special chars $word = preg_quote($word, '/'); + $search = "/($word)/i"; // must replace with placeholders in case one of the search terms is @@ -297,7 +301,9 @@ function search_remove_ignored_words($query, $format = 'array') { global $CONFIG; // don't worry about "s or boolean operators - $query = str_replace(array('"', '-', '+', '~'), '', stripslashes(strip_tags($query))); + //$query = str_replace(array('"', '-', '+', '~'), '', stripslashes(strip_tags($query))); + $query = stripslashes(strip_tags($query)); + $words = explode(' ', $query); $min_chars = $CONFIG->search_info['min_chars']; @@ -386,12 +392,8 @@ function search_get_where_sql($table, $fields, $params, $use_fulltext = TRUE) { $fields[$i] = "$table.$field"; } } - - // if we're not using full text, rewrite the query for bool mode. - // exploiting a feature(ish) of bool mode where +-word is the same as -word - if (!$use_fulltext) { - $query = '+' . str_replace(' ', ' +', $query); - } + + $where = ''; // if query is shorter than the min for fts words // it's likely a single acronym or similar @@ -405,22 +407,30 @@ function search_get_where_sql($table, $fields, $params, $use_fulltext = TRUE) { $likes_str = implode(' OR ', $likes); $where = "($likes_str)"; } else { - // if using advanced or paired "s, switch into boolean mode - if (!$use_fulltext - || (isset($params['advanced_search']) && $params['advanced_search']) - || elgg_substr_count($query, '"') >= 2 ) { + // if we're not using full text, rewrite the query for bool mode. + // exploiting a feature(ish) of bool mode where +-word is the same as -word + if (!$use_fulltext) { + $query = '+' . str_replace(' ', ' +', $query); + } + + // if using advanced, boolean operators, or paired "s, switch into boolean mode + $booleans_used = preg_match("/([\-\+~])([\w]+)/i", $query); + $advanced_search = (isset($params['advanced_search']) && $params['advanced_search']); + $quotes_used = (elgg_substr_count($query, '"') >= 2); + + if (!$use_fulltext || $booleans_used || $advanced_search || $quotes_used) { $options = 'IN BOOLEAN MODE'; } else { // natural language mode is default and this keyword isn't supported in < 5.1 //$options = 'IN NATURAL LANGUAGE MODE'; $options = ''; } - + // if short query, use query expansion. // @todo doesn't seem to be working well. - if (elgg_strlen($query) < 5) { - //$options .= ' WITH QUERY EXPANSION'; - } +// if (elgg_strlen($query) < 5) { +// $options .= ' WITH QUERY EXPANSION'; +// } $query = sanitise_string($query); $fields_str = implode(',', $fields); diff --git a/version.php b/version.php index 6fc5f8f50..e8dd540f7 100644 --- a/version.php +++ b/version.php @@ -12,7 +12,7 @@ // YYYYMMDD = Elgg Date // XX = Interim incrementer -$version = 2010061501; +$version = 2010062401; // Human-friendly version name $release = '1.8-svn'; diff --git a/views/default/friends/picker.php b/views/default/friends/picker.php index 4b8d10111..7b47ed675 100644 --- a/views/default/friends/picker.php +++ b/views/default/friends/picker.php @@ -83,6 +83,14 @@ if (is_array($vars['entities']) && sizeof($vars['entities'])) { } } +// sort users in letters alphabetically +foreach ($users as $letter => $letter_users) { + usort($letter_users, create_function('$a, $b', ' + return strcasecmp($a->name, $b->name); + ')); + $users[$letter] = $letter_users; +} + if (!$callback) { ?> diff --git a/views/default/input/checkboxes.php b/views/default/input/checkboxes.php index fa7c0c34c..088a97709 100644 --- a/views/default/input/checkboxes.php +++ b/views/default/input/checkboxes.php @@ -2,52 +2,97 @@ /** * Elgg checkbox input * Displays a checkbox input field + * NB: This also includes a hidden input with the same name as the checkboxes + * to make sure something is sent to the server. The default value is 0. + * If using JS, be specific to avoid selecting the hidden default value: + * $('input[type=checkbox][name=internalname]) * * @package Elgg * @subpackage Core * @author Curverider Ltd * @link http://elgg.org/ * - * @uses $vars['value'] The current value, if any - * @uses $vars['js'] Any Javascript to enter into the input tag - * @uses $vars['internalname'] The name of the input field - * @uses $vars['options'] An array of strings representing the label => options for the checkbox field + * @uses string $vars['internalname'] The name of the input fields (Forced to an array by appending []) + * @uses array $vars['options'] An array of strings representing the label => option for the each checkbox field + * @uses string $vars['internalid'] The id for each input field. Optional (Only use this with a single value.) + * @uses string $vars['default'] The default value to send if nothing is checked. Optional, defaults to 0. + * @uses bool $vars['disabled'] Make all input elements disabled. Optional. + * @uses string $vars['value'] The current value. Optional. + * @uses string $vars['class'] The class of each input element. Optional. + * @uses string $vars['js'] Any Javascript to enter into the input tag. Optional. * */ -$class = $vars['class']; -if (!$class) { - $class = "input_checkboxes"; +if (!isset($vars['value']) || $vars['value'] === FALSE) { + $vars['value'] = elgg_get_sticky_value($vars['internalname']); } -if (!isset($vars['value']) || $vars['value'] === FALSE) { - $vars['value'] = elgg_get_sticky_value($vars['internalname']); -} +$class = (isset($vars['class'])) ? $vars['class'] : 'input_checkboxes'; +$value = (isset($vars['value'])) ? $vars['value'] : NULL; +$value_array = (is_array($value)) ? array_map('strtolower', $value) : array(strtolower($value)); +$internalname = (isset($vars['internalname'])) ? $vars['internalname'] : ''; +$options = (isset($vars['options']) && is_array($vars['options'])) ? $vars['options'] : array(); +$default = (isset($vars['default'])) ? $vars['default'] : 0; -foreach($vars['options'] as $label => $option) { - //if (!in_array($option,$vars['value'])) { - if (is_array($vars['value'])) { - $valarray = $vars['value']; - $valarray = array_map('strtolower', $valarray); - if (!in_array(strtolower($option),$valarray)) { - $selected = ""; - } else { - $selected = "checked = \"checked\""; +$id = (isset($vars['internalid'])) ? $vars['internalid'] : ''; +$disabled = (isset($vars['disabled'])) ? $vars['disabled'] : FALSE; +$js = (isset($vars['js'])) ? $vars['js'] : ''; + +if ($options) { + // include a default value so if nothing is checked 0 will be passed. + if ($internalname) { + echo "<input type=\"hidden\" name=\"$internalname\" value=\"$default\">"; + } + + foreach($options as $label => $option) { + // @hack - This sorta checks if options is not an assoc array and then + // ignores the label (because it's just the index) and sets the value ($option) + // as the label. + // Wow. + $labelint = (int) $label; + + if ("{$label}" == "{$labelint}") { + $label = $option; } - } else { - if (strtolower($option) != strtolower($vars['value'])) { - $selected = ""; + + if (!in_array(strtolower($option), $value_array)) { + $selected = FALSE; } else { - $selected = "checked = \"checked\""; + $selected = TRUE; + } + + $attr = array( + 'type="checkbox"', + 'value="' . htmlentities($option, ENT_QUOTES, 'UTF-8') . '"' + ); + + if ($id) { + $attr[] = "id=\"$id\""; } - } - $labelint = (int) $label; - if ("{$label}" == "{$labelint}") { - $label = $option; - } - if (isset($vars['internalid'])) $id = "id=\"{$vars['internalid']}\""; - $disabled = ""; - if ($vars['disabled']) $disabled = ' disabled="yes" '; - echo "<label><input type=\"checkbox\" $id $disabled {$vars['js']} name=\"{$vars['internalname']}[]\" value=\"".htmlentities($option, ENT_QUOTES, 'UTF-8')."\" {$selected} class=\"$class\" />{$label}</label><br />"; + if ($class) { + $attr[] = "class=\"$class\""; + } + + if ($disabled) { + $attr[] = 'disabled="yes"'; + } + + if ($selected) { + $attr[] = 'checked = "checked"'; + } + + if ($js) { + $attr[] = $js; + } + + if ($internalname) { + // @todo this really, really should only add the []s if there are > 1 element in options. + $attr[] = "name=\"{$internalname}[]\""; + } + + $attr_str = implode(' ', $attr); + + echo "<label><input $attr_str />$label</label><br />"; + } }
\ No newline at end of file |