From 949a3f0c2ea1804577ff69d92f811ced71a79976 Mon Sep 17 00:00:00 2001 From: Jerome Bakker Date: Wed, 3 Oct 2012 14:02:11 +0200 Subject: correct singual usage of type in elgg_get_entities_* functions --- engine/tests/api/entity_getter_functions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engine/tests') diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index 9db248de9..d255c2e67 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2648,7 +2648,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { $name = 'test_annotation_' . rand(0, 9999); $values = array(); $options = array( - 'types' => 'object', + 'type' => 'object', 'subtypes' => $subtypes, 'limit' => 5 ); @@ -2687,7 +2687,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { $order = array_keys($values); $options = array( - 'types' => 'object', + 'type' => 'object', 'subtypes' => $subtypes, 'limit' => 5, 'annotation_name' => $name, -- cgit v1.2.3 From e33d1eba6a158699174de2747de6d6e654c03407 Mon Sep 17 00:00:00 2001 From: Jerome Bakker Date: Wed, 3 Oct 2012 14:11:41 +0200 Subject: correct singual usage of subtype in elgg_get_entities_* functions --- engine/lib/deprecated-1.8.php | 10 +++++----- engine/lib/sites.php | 2 +- engine/lib/users.php | 4 ++-- engine/tests/api/entity_getter_functions.php | 2 +- mod/categories/pages/categories/listing.php | 2 +- mod/file/pages/file/owner.php | 2 +- mod/file/pages/file/search.php | 2 +- mod/file/pages/file/world.php | 2 +- mod/pages/pages/pages/owner.php | 2 +- mod/pages/pages/pages/world.php | 2 +- .../default/admin/administer_utilities/reportedcontent.php | 2 +- .../views/default/widgets/reportedcontent/content.php | 2 +- mod/thewire/views/default/thewire/profile_status.php | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php index e967df3dd..622b58212 100644 --- a/engine/lib/deprecated-1.8.php +++ b/engine/lib/deprecated-1.8.php @@ -87,7 +87,7 @@ function list_entities_from_access_id($access_id, $entity_type = "", $entity_sub elgg_deprecated_notice("All list_entities* functions were deprecated in 1.8. Use elgg_list_entities* instead.", 1.8); echo elgg_list_entities_from_access_id(array('access_id' => $access_id, - 'types' => $entity_type, 'subtypes' => $entity_subtype, 'owner_guids' => $owner_guid, + 'types' => $entity_type, 'subtype' => $entity_subtype, 'owner_guids' => $owner_guid, 'limit' => $limit, 'full_view' => $fullview, 'list_type_toggle' => $listtypetoggle, 'pagination' => $pagination,)); } @@ -1315,7 +1315,7 @@ function list_entities_from_metadata($meta_name, $meta_value = "", $entity_type 'metadata_name' => $meta_name, 'metadata_value' => $meta_value, 'types' => $entity_type, - 'subtypes' => $entity_subtype, + 'subtype' => $entity_subtype, 'limit' => $limit, 'offset' => $offset, 'count' => TRUE, @@ -2121,7 +2121,7 @@ $fullview = true, $listtypetoggle = false, $pagination = true, $order_by = '') { 'relationship_guid' => $relationship_guid, 'inverse_relationship' => $inverse_relationship, 'types' => $type, - 'subtypes' => $subtype, + 'subtype' => $subtype, 'owner_guid' => $owner_guid, 'order_by' => $order_by, 'limit' => $limit, @@ -2567,7 +2567,7 @@ $owner_guid = "", $owner_relationship = "") { 'relationship_guid' => $owner_guid[0], 'inverse_relationship' => FALSE, 'type' => 'user', - 'subtypes' => $subtype, + 'subtype' => $subtype, 'limit' => 9999)) ) { @@ -2722,7 +2722,7 @@ function get_site_collections($site_guid, $subtype = "", $limit = 10, $offset = 'relationship_guid' => $site_guid, 'inverse_relationship' => TRUE, 'type' => 'collection', - 'subtypes' => $subtype, + 'subtype' => $subtype, 'limit' => $limit, 'offset' => $offset )); diff --git a/engine/lib/sites.php b/engine/lib/sites.php index 805dacd2d..236fbc28e 100644 --- a/engine/lib/sites.php +++ b/engine/lib/sites.php @@ -184,7 +184,7 @@ function get_site_objects($site_guid, $subtype = "", $limit = 10, $offset = 0) { 'relationship_guid' => $site_guid, 'inverse_relationship' => TRUE, 'type' => 'object', - 'subtypes' => $subtype, + 'subtype' => $subtype, 'limit' => $limit, 'offset' => $offset )); diff --git a/engine/lib/users.php b/engine/lib/users.php index 7dc6b7c2d..6b0b1429b 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -387,7 +387,7 @@ $offset = 0) { 'relationship' => 'friend', 'relationship_guid' => $user_guid, 'type' => 'user', - 'subtypes' => $subtype, + 'subtype' => $subtype, 'limit' => $limit, 'offset' => $offset )); @@ -411,7 +411,7 @@ $offset = 0) { 'relationship_guid' => $user_guid, 'inverse_relationship' => TRUE, 'type' => 'user', - 'subtypes' => $subtype, + 'subtype' => $subtype, 'limit' => $limit, 'offset' => $offset )); diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index d255c2e67..6f7a6145e 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -426,7 +426,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { $options = array( 'types' => $types, - 'subtypes' => $subtype + 'subtype' => $subtype ); $es = elgg_get_entities($options); diff --git a/mod/categories/pages/categories/listing.php b/mod/categories/pages/categories/listing.php index 8924506e9..4e677d5c4 100644 --- a/mod/categories/pages/categories/listing.php +++ b/mod/categories/pages/categories/listing.php @@ -16,7 +16,7 @@ $params = array( 'metadata_name' => 'universal_categories', 'metadata_value' => $category, 'types' => $type, - 'subtypes' => $subtype, + 'subtype' => $subtype, 'owner_guid' => $owner_guid, 'limit' => $limit, 'full_view' => FALSE, diff --git a/mod/file/pages/file/owner.php b/mod/file/pages/file/owner.php index 1409a404e..d7f057f2a 100644 --- a/mod/file/pages/file/owner.php +++ b/mod/file/pages/file/owner.php @@ -37,7 +37,7 @@ $title = elgg_echo("file:user", array($owner->name)); // List files $content = elgg_list_entities(array( 'type' => 'object', - 'subtypes' => 'file', + 'subtype' => 'file', 'container_guid' => $owner->guid, 'limit' => 10, 'full_view' => FALSE, diff --git a/mod/file/pages/file/search.php b/mod/file/pages/file/search.php index 35f8a7db7..d60dfb755 100644 --- a/mod/file/pages/file/search.php +++ b/mod/file/pages/file/search.php @@ -75,7 +75,7 @@ if ($listtype == "gallery") { $params = array( 'type' => 'object', - 'subtypes' => 'file', + 'subtype' => 'file', 'container_guid' => $page_owner_guid, 'limit' => $limit, 'full_view' => false, diff --git a/mod/file/pages/file/world.php b/mod/file/pages/file/world.php index 8cf8ad138..8e6c87f26 100644 --- a/mod/file/pages/file/world.php +++ b/mod/file/pages/file/world.php @@ -15,7 +15,7 @@ $title = elgg_echo('file:all'); $content = elgg_list_entities(array( 'type' => 'object', - 'subtypes' => 'file', + 'subtype' => 'file', 'limit' => $limit, 'full_view' => FALSE )); diff --git a/mod/pages/pages/pages/owner.php b/mod/pages/pages/pages/owner.php index a061225e2..48199368c 100644 --- a/mod/pages/pages/pages/owner.php +++ b/mod/pages/pages/pages/owner.php @@ -21,7 +21,7 @@ elgg_register_title_button(); $content = elgg_list_entities(array( 'type' => 'object', - 'subtypes' => 'page_top', + 'subtype' => 'page_top', 'container_guid' => elgg_get_page_owner_guid(), 'full_view' => false, )); diff --git a/mod/pages/pages/pages/world.php b/mod/pages/pages/pages/world.php index e5a29eb63..c130a6bd6 100644 --- a/mod/pages/pages/pages/world.php +++ b/mod/pages/pages/pages/world.php @@ -14,7 +14,7 @@ elgg_register_title_button(); $content = elgg_list_entities(array( 'type' => 'object', - 'subtypes' => 'page_top', + 'subtype' => 'page_top', 'full_view' => false, )); if (!$content) { diff --git a/mod/reportedcontent/views/default/admin/administer_utilities/reportedcontent.php b/mod/reportedcontent/views/default/admin/administer_utilities/reportedcontent.php index c37761f32..ed52a536d 100644 --- a/mod/reportedcontent/views/default/admin/administer_utilities/reportedcontent.php +++ b/mod/reportedcontent/views/default/admin/administer_utilities/reportedcontent.php @@ -5,7 +5,7 @@ * @package ElggReportedContent */ -$list = elgg_list_entities(array('type' => 'object', 'subtypes' => 'reported_content')); +$list = elgg_list_entities(array('type' => 'object', 'subtype' => 'reported_content')); if (!$list) { $list = '

' . elgg_echo('reportedcontent:none') . '

'; } diff --git a/mod/reportedcontent/views/default/widgets/reportedcontent/content.php b/mod/reportedcontent/views/default/widgets/reportedcontent/content.php index d6af8e87b..0095decca 100644 --- a/mod/reportedcontent/views/default/widgets/reportedcontent/content.php +++ b/mod/reportedcontent/views/default/widgets/reportedcontent/content.php @@ -5,7 +5,7 @@ $list = elgg_list_entities(array( 'type' => 'object', - 'subtypes' => 'reported_content', + 'subtype' => 'reported_content', 'limit' => $vars['entity']->num_display, 'pagination' => false, )); diff --git a/mod/thewire/views/default/thewire/profile_status.php b/mod/thewire/views/default/thewire/profile_status.php index ef0d550d2..26e1403fe 100644 --- a/mod/thewire/views/default/thewire/profile_status.php +++ b/mod/thewire/views/default/thewire/profile_status.php @@ -10,7 +10,7 @@ $owner = $vars['entity']->guid; //grab the user's latest from the wire $params = array( 'type' => 'object', - 'subtypes' => 'thewire', + 'subtype' => 'thewire', 'owner_guid' => $owner, 'limit' => 1, ); -- cgit v1.2.3 From 8f7bd6a446c85d8200e384ad320ea2507a850b0e Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Wed, 27 Feb 2013 10:36:47 -0500 Subject: Fixes #5066. Empty subtypes are handled the same way for both 'subtype' and 'subtypes' --- engine/lib/entities.php | 24 ++++++++++++++------ engine/tests/api/entity_getter_functions.php | 34 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 7 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/entities.php b/engine/lib/entities.php index 25c927ac6..156eec040 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -1219,14 +1219,24 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair $subtype_ids = array(); if ($subtypes) { foreach ($subtypes as $subtype) { - // check that the subtype is valid (with ELGG_ENTITIES_NO_VALUE being a valid subtype) - // @todo simplify this logic - if (ELGG_ENTITIES_NO_VALUE === $subtype || $subtype_id = get_subtype_id($type, $subtype)) { - $subtype_ids[] = (ELGG_ENTITIES_NO_VALUE === $subtype) ? ELGG_ENTITIES_NO_VALUE : $subtype_id; - } else { - $valid_subtypes_count--; - elgg_log("Type-subtype '$type:$subtype' does not exist!", 'NOTICE'); + // check that the subtype is valid + if (!$subtype && ELGG_ENTITIES_NO_VALUE === $subtype) { + // subtype value is 0 + $subtype_ids[] = ELGG_ENTITIES_NO_VALUE; + } elseif (!$subtype) { + // subtype is ignored. + // this handles ELGG_ENTITIES_ANY_VALUE, '', and anything falsy that isn't 0 continue; + } else { + $subtype_id = get_subtype_id($type, $subtype); + + if ($subtype_id) { + $subtype_ids[] = $subtype_id; + } else { + $valid_subtypes_count--; + elgg_log("Type-subtype '$type:$subtype' does not exist!", 'NOTICE'); + continue; + } } } diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index 6f7a6145e..52470e19d 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2817,4 +2817,38 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { $entities = elgg_get_entities($options); $this->assertFalse($entities); } + + public function testEGEEmptySubtypePlurality() { + $options = array( + 'type' => 'user', + 'subtypes' => '' + ); + + $entities = elgg_get_entities($options); + $this->assertTrue(is_array($entities)); + + $options = array( + 'type' => 'user', + 'subtype' => '' + ); + + $entities = elgg_get_entities($options); + $this->assertTrue(is_array($entities)); + + $options = array( + 'type' => 'user', + 'subtype' => array('') + ); + + $entities = elgg_get_entities($options); + $this->assertTrue(is_array($entities)); + + $options = array( + 'type' => 'user', + 'subtypes' => array('') + ); + + $entities = elgg_get_entities($options); + $this->assertTrue(is_array($entities)); + } } -- cgit v1.2.3 From 6955850778c68412983e2acf4b26f4bece199eae Mon Sep 17 00:00:00 2001 From: cash Date: Wed, 6 Mar 2013 16:12:33 -0500 Subject: added a unit test for checking counting entities from egefac --- engine/tests/api/entity_getter_functions.php | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'engine/tests') diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index 52470e19d..7bf8ef04a 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2729,6 +2729,36 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { } } + public function testElggGetEntitiesFromAnnotationCalculationCount() { + // add two annotations with a unique name to an entity + // then count the number of entities with that annotation name + + $subtypes = $this->getRandomValidSubtypes(array('object'), 1); + $name = 'test_annotation_' . rand(0, 9999); + $values = array(); + $options = array( + 'type' => 'object', + 'subtypes' => $subtypes, + 'limit' => 1 + ); + $es = elgg_get_entities($options); + $entity = $es[0]; + $value = rand(0, 9999); + $entity->annotate($name, $value); + $value = rand(0, 9999); + $entity->annotate($name, $value); + + $options = array( + 'type' => 'object', + 'subtypes' => $subtypes, + 'annotation_name' => $name, + 'calculation' => 'count', + 'count' => true, + ); + $count = (int)elgg_get_entities_from_annotation_calculation($options); + $this->assertEqual(1, $count); + } + public function testElggGetAnnotationsAnnotationNames() { $options = array('annotation_names' => array()); $a_e_map = array(); -- cgit v1.2.3 From cb8a932702a66a8d8ec69982441e71bde8fd1b5c Mon Sep 17 00:00:00 2001 From: cash Date: Sat, 30 Mar 2013 12:04:19 -0400 Subject: Fixes #4867 handling boolean false values as metadata pair value --- engine/lib/metadata.php | 2 ++ engine/tests/api/metadata.php | 14 ++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'engine/tests') diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index a1ebfa5f1..ad926a49a 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -619,6 +619,8 @@ $owner_guids = NULL) { // if the operand is IN don't quote it because quoting should be done already. if (is_numeric($pair['value'])) { $value = sanitise_string($pair['value']); + } else if (is_bool($pair['value'])) { + $value = (int) $pair['value']; } else if (is_array($pair['value'])) { $values_array = array(); diff --git a/engine/tests/api/metadata.php b/engine/tests/api/metadata.php index 825290d80..0862341c1 100644 --- a/engine/tests/api/metadata.php +++ b/engine/tests/api/metadata.php @@ -123,6 +123,20 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest { $e->delete(); } + /** + * https://github.com/Elgg/Elgg/issues/4867 + */ + public function testElggGetEntityMetadataWhereSqlWithFalseValue() { + $pair = array('name' => 'test' , 'value' => false); + $result = elgg_get_entity_metadata_where_sql('e', 'metadata', null, null, $pair); + $where = preg_replace( '/\s+/', ' ', $result['wheres'][0]); + $this->assertTrue(strpos($where, "msn1.string = 'test' AND BINARY msv1.string = 0") > 0); + + $result = elgg_get_entity_metadata_where_sql('e', 'metadata', array('test'), array(false)); + $where = preg_replace( '/\s+/', ' ', $result['wheres'][0]); + $this->assertTrue(strpos($where, "msn.string IN ('test')) AND ( BINARY msv.string IN ('0')")); + } + // Make sure metadata with multiple values is correctly deleted when re-written // by another user // http://trac.elgg.org/ticket/2776 -- cgit v1.2.3 From 5ccc0540fd28cc1620ffca10e3aed92319e78794 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sun, 31 Mar 2013 21:09:07 -0400 Subject: Fixes #4972: More robust friendly titles implementation --- engine/classes/ElggTranslit.php | 15 ++++++++++++--- engine/lib/output.php | 8 +++----- engine/tests/regression/trac_bugs.php | 16 +++++++++------- 3 files changed, 24 insertions(+), 15 deletions(-) (limited to 'engine/tests') diff --git a/engine/classes/ElggTranslit.php b/engine/classes/ElggTranslit.php index 601965c11..4ae1d2479 100644 --- a/engine/classes/ElggTranslit.php +++ b/engine/classes/ElggTranslit.php @@ -49,10 +49,19 @@ class ElggTranslit { // Internationalization, AND 日本語! $string = self::transliterateAscii($string); - // more translation + // allow HTML tags in titles + $string = preg_replace('~<([a-zA-Z][^>]*)>~', ' $1 ', $string); + + // more substitutions + // @todo put these somewhere else $string = strtr($string, array( - // Euro/GBP - "\xE2\x82\xAC" /* € */ => 'E', "\xC2\xA3" /* £ */ => 'GBP', + // currency + "\xE2\x82\xAC" /* € */ => ' E ', + "\xC2\xA3" /* £ */ => ' GBP ', + + "&" => ' and ', + ">" => ' greater than ', + "<" => ' less than ', )); // remove all ASCII except 0-9a-zA-Z, hyphen, underscore, and whitespace diff --git a/engine/lib/output.php b/engine/lib/output.php index da8e1ab86..c5a04989b 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -284,11 +284,9 @@ function elgg_get_friendly_title($title) { return $result; } - // handle some special cases - $title = str_replace('&', 'and', $title); - // quotes and angle brackets stored in the database as html encoded - $title = htmlspecialchars_decode($title); - + // titles are often stored HTML encoded + $title = html_entity_decode($title, ENT_QUOTES, 'UTF-8'); + $title = ElggTranslit::urlize($title); return $title; diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 691433a41..58444dd39 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -206,21 +206,23 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { */ public function test_friendly_title() { $cases = array( + // acid test + "B&N > Amazon, OK? 'hey!' $34" + => "b-and-n-greater-than-amazon-ok-bold-hey-34", + // hyphen, underscore and ASCII whitespace replaced by separator, // other non-alphanumeric ASCII removed - "a-a_a a\na\ra\ta\va!a\"a#a\$a%a&a'a(a)a*a+a,a.a/a:a;aa?a@a[a\\a]a^a`a{a|a}a~a" - => "a-a-a-a-a-a-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - + "a-a_a a\na\ra\ta\va!a\"a#a\$a%a&a'a(a)a*a+a,a.a/a:a;a=a?a@a[a\\a]a^a`a{a|a}a~a" + => "a-a-a-a-a-a-aaaaaaa-and-aaaaaaaaaaaaaaaaaaaaaaa", + // separators trimmed - "-_ hello _-" => "hello", + "-_ hello _-" + => "hello", // accents removed, lower case, other multibyte chars are URL encoded "I\xC3\xB1t\xC3\xABrn\xC3\xA2ti\xC3\xB4n\xC3\xA0liz\xC3\xA6ti\xC3\xB8n, AND \xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" // Iñtërnâtiônàlizætiøn, AND 日本語 => 'internationalizaetion-and-%E6%97%A5%E6%9C%AC%E8%AA%9E', - - // some HTML entity replacements - "Me & You" => 'me-and-you', ); // where available, string is converted to NFC before transliteration -- cgit v1.2.3 From 5dd3d179f43b47231dab5dab5d5d9482a9810ef7 Mon Sep 17 00:00:00 2001 From: cash Date: Sat, 13 Apr 2013 13:36:56 -0400 Subject: removed query cache reset from unit test of acl. If this is needed, is bug in elgg core --- engine/tests/api/access_collections.php | 3 --- 1 file changed, 3 deletions(-) (limited to 'engine/tests') diff --git a/engine/tests/api/access_collections.php b/engine/tests/api/access_collections.php index ebcd7d318..4acfae596 100644 --- a/engine/tests/api/access_collections.php +++ b/engine/tests/api/access_collections.php @@ -54,7 +54,6 @@ class ElggCoreAccessCollectionsTest extends ElggCoreUnitTest { } public function testCreateGetDeleteACL() { - global $DB_QUERY_CACHE; $acl_name = 'test access collection'; $acl_id = create_access_collection($acl_name); @@ -67,8 +66,6 @@ class ElggCoreAccessCollectionsTest extends ElggCoreUnitTest { $this->assertEqual($acl->id, $acl_id); if ($acl) { - $DB_QUERY_CACHE = array(); - $this->assertEqual($acl->name, $acl_name); $result = delete_access_collection($acl_id); -- cgit v1.2.3 From 834c4ad0bf82f28949b108eb6c957fde3c18e1ce Mon Sep 17 00:00:00 2001 From: Cash Costello Date: Sat, 20 Apr 2013 11:07:44 -0400 Subject: Fixes #5369 allows ! in urls and adds unit tests --- engine/lib/output.php | 25 ++++++++++------- engine/tests/regression/trac_bugs.php | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 10 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/output.php b/engine/lib/output.php index c5a04989b..fe5bbcaaf 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -13,28 +13,33 @@ * @param string $text The input string * * @return string The output string with formatted links - **/ + */ function parse_urls($text) { + + // URI specification: http://www.ietf.org/rfc/rfc3986.txt + // This varies from the specification in the following ways: + // * Supports non-ascii characters + // * Does not allow parentheses and single quotes + // * Cuts off commas, exclamation points, and periods off as last character + // @todo this causes problems with // must be in format (no space). // By default htmlawed rewrites tags to this format. // if PHP supported conditional negative lookbehinds we could use this: // $r = preg_replace_callback('/(?"\'\!\(\),]+)/i', - // - // we can put , in the list of excluded char but need to keep . because of domain names. - // it is removed in the callback. - $r = preg_replace_callback('/(?"\'\!\(\),]+)/i', + $r = preg_replace_callback('/(?"\'\(\)]+)/i', create_function( '$matches', ' $url = $matches[1]; - $period = \'\'; - if (substr($url, -1, 1) == \'.\') { - $period = \'.\'; - $url = trim($url, \'.\'); + $punc = \'\'; + $last = substr($url, -1, 1); + if (in_array($last, array(".", "!", ","))) { + $punc = $last; + $url = rtrim($url, ".!,"); } $urltext = str_replace("/", "/", $url); - return "$urltext$period"; + return "$urltext$punc"; ' ), $text); diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 58444dd39..83b78bc6b 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -236,4 +236,56 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { $this->assertIdentical($expected, $friendly_title); } } + + /** + * Test #5369 -- parse_urls() + * https://github.com/Elgg/Elgg/issues/5369 + */ + public function test_parse_urls() { + + $cases = array( + 'no.link.here' => + 'no.link.here', + 'simple link http://example.org test' => + 'simple link http://example.org test', + 'non-ascii http://ñew.org/ test' => + 'non-ascii http://ñew.org/ test', + + // section 2.1 + 'percent encoded http://example.org/a%20b test' => + 'percent encoded http://example.org/a%20b test', + // section 2.2: skipping single quote and parenthese + 'reserved characters http://example.org/:/?#[]@!$&*+,;= test' => + 'reserved characters http://example.org/:/?#[]@!$&*+,;= test', + // section 2.3 + 'unreserved characters http://example.org/a1-._~ test' => + 'unreserved characters http://example.org/a1-._~ test', + + 'parameters http://example.org/?val[]=1&val[]=2 test' => + 'parameters http://example.org/?val[]=1&val[]=2 test', + 'port http://example.org:80/ test' => + 'port http://example.org:80/ test', + + 'parentheses (http://www.google.com) test' => + 'parentheses (http://www.google.com) test', + 'comma http://elgg.org, test' => + 'comma http://elgg.org, test', + 'period http://elgg.org. test' => + 'period http://elgg.org. test', + 'exclamation http://elgg.org! test' => + 'exclamation http://elgg.org! test', + + 'already anchor twitter test' => + 'already anchor twitter test', + + 'ssl https://example.org/ test' => + 'ssl https://example.org/ test', + 'ftp ftp://example.org/ test' => + 'ftp ftp://example.org/ test', + + ); + foreach ($cases as $input => $output) { + $this->assertEqual($output, parse_urls($input)); + } + } } -- cgit v1.2.3 From 164ff10b46d5917c7ab6ad068abf10e492464691 Mon Sep 17 00:00:00 2001 From: cash Date: Sat, 20 Apr 2013 12:08:27 -0400 Subject: Fixes #5244 adds nofollow to anchor tags created by parse_urls() --- engine/lib/output.php | 2 +- engine/tests/regression/trac_bugs.php | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/output.php b/engine/lib/output.php index fe5bbcaaf..6905b9b71 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -39,7 +39,7 @@ function parse_urls($text) { $url = rtrim($url, ".!,"); } $urltext = str_replace("/", "/", $url); - return "$urltext$punc"; + return "$urltext$punc"; ' ), $text); diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 83b78bc6b..4de9c306b 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -247,41 +247,41 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { 'no.link.here' => 'no.link.here', 'simple link http://example.org test' => - 'simple link http://example.org test', + 'simple link http://example.org test', 'non-ascii http://ñew.org/ test' => - 'non-ascii http://ñew.org/ test', + 'non-ascii http://ñew.org/ test', // section 2.1 'percent encoded http://example.org/a%20b test' => - 'percent encoded http://example.org/a%20b test', + 'percent encoded http://example.org/a%20b test', // section 2.2: skipping single quote and parenthese 'reserved characters http://example.org/:/?#[]@!$&*+,;= test' => - 'reserved characters http://example.org/:/?#[]@!$&*+,;= test', + 'reserved characters http://example.org/:/?#[]@!$&*+,;= test', // section 2.3 'unreserved characters http://example.org/a1-._~ test' => - 'unreserved characters http://example.org/a1-._~ test', + 'unreserved characters http://example.org/a1-._~ test', 'parameters http://example.org/?val[]=1&val[]=2 test' => - 'parameters http://example.org/?val[]=1&val[]=2 test', + 'parameters http://example.org/?val[]=1&val[]=2 test', 'port http://example.org:80/ test' => - 'port http://example.org:80/ test', + 'port http://example.org:80/ test', 'parentheses (http://www.google.com) test' => - 'parentheses (http://www.google.com) test', + 'parentheses (http://www.google.com) test', 'comma http://elgg.org, test' => - 'comma http://elgg.org, test', + 'comma http://elgg.org, test', 'period http://elgg.org. test' => - 'period http://elgg.org. test', + 'period http://elgg.org. test', 'exclamation http://elgg.org! test' => - 'exclamation http://elgg.org! test', + 'exclamation http://elgg.org! test', 'already anchor twitter test' => 'already anchor twitter test', 'ssl https://example.org/ test' => - 'ssl https://example.org/ test', + 'ssl https://example.org/ test', 'ftp ftp://example.org/ test' => - 'ftp ftp://example.org/ test', + 'ftp ftp://example.org/ test', ); foreach ($cases as $input => $output) { -- cgit v1.2.3 From cd7922c58f3f2d04b8ca4bcf336ecda2787c821e Mon Sep 17 00:00:00 2001 From: Jeff Tilson Date: Mon, 29 Apr 2013 13:38:42 -0400 Subject: Fixes #2057 (broken internet archive links) --- engine/lib/output.php | 2 +- engine/tests/regression/trac_bugs.php | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'engine/tests') diff --git a/engine/lib/output.php b/engine/lib/output.php index 6905b9b71..5adc01053 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -27,7 +27,7 @@ function parse_urls($text) { // By default htmlawed rewrites tags to this format. // if PHP supported conditional negative lookbehinds we could use this: // $r = preg_replace_callback('/(?"\'\!\(\),]+)/i', - $r = preg_replace_callback('/(?"\'\(\)]+)/i', + $r = preg_replace_callback('/(?"\'\(\)]+)/i', create_function( '$matches', ' diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 4de9c306b..b791dcad3 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -288,4 +288,13 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { $this->assertEqual($output, parse_urls($input)); } } + + /** + * Test #2057 -- parse_urls() + * https://github.com/Elgg/Elgg/issues/2057 + */ + public function test_archive_url() { + $input = 'google'; + $this->assertEqual($input, parse_urls($input)); + } } -- cgit v1.2.3 From 003439fd46cb5e0dedfabf6e49110b3bdffbefe9 Mon Sep 17 00:00:00 2001 From: Jeff Tilson Date: Mon, 29 Apr 2013 14:06:18 -0400 Subject: Including internet archive url test in existing test_parse_url function --- engine/tests/regression/trac_bugs.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'engine/tests') diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index b791dcad3..cb3f20421 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -282,19 +282,12 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { 'ssl https://example.org/ test', 'ftp ftp://example.org/ test' => 'ftp ftp://example.org/ test', + 'google' => + 'google' ); foreach ($cases as $input => $output) { $this->assertEqual($output, parse_urls($input)); } } - - /** - * Test #2057 -- parse_urls() - * https://github.com/Elgg/Elgg/issues/2057 - */ - public function test_archive_url() { - $input = 'google'; - $this->assertEqual($input, parse_urls($input)); - } } -- cgit v1.2.3 From f04fdceb5941df31e1ac94f7fb586c2688813da7 Mon Sep 17 00:00:00 2001 From: Jeff Tilson Date: Mon, 29 Apr 2013 14:42:24 -0400 Subject: Adding single quote anchor to parse_url unit test --- engine/tests/regression/trac_bugs.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engine/tests') diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index cb3f20421..b7654a794 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -282,8 +282,12 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { 'ssl https://example.org/ test', 'ftp ftp://example.org/ test' => 'ftp ftp://example.org/ test', - 'google' => - 'google' + + 'web archive anchor google' => + 'web archive anchor google', + + 'single quotes already anchor yahoo' => + 'single quotes already anchor yahoo' ); foreach ($cases as $input => $output) { -- cgit v1.2.3 From d785357ba7cb9e8a6bb7b2f91bf389e6bd1e636b Mon Sep 17 00:00:00 2001 From: cash Date: Thu, 2 May 2013 22:02:41 -0400 Subject: Fixes #5418 adds enabled clause for annotations --- engine/lib/metastrings.php | 14 ++++++++------ engine/tests/api/metastrings.php | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 8 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index f49b4a163..39a81c6d0 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -421,6 +421,8 @@ function elgg_get_metastring_based_objects($options) { if ($metastring_clauses) { $wheres = array_merge($wheres, $metastring_clauses['wheres']); $joins = array_merge($joins, $metastring_clauses['joins']); + } else { + $wheres[] = get_access_sql_suffix('n_table'); } if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) { @@ -510,7 +512,7 @@ function elgg_get_metastring_sql($table, $names = null, $values = null, && !$ids && (!$pairs && $pairs !== 0)) { - return ''; + return array(); } $db_prefix = elgg_get_config('dbprefix'); @@ -520,8 +522,6 @@ function elgg_get_metastring_sql($table, $names = null, $values = null, // only supported on values. $binary = ($case_sensitive) ? ' BINARY ' : ''; - $access = get_access_sql_suffix($table); - $return = array ( 'joins' => array (), 'wheres' => array() @@ -586,13 +586,15 @@ function elgg_get_metastring_sql($table, $names = null, $values = null, } if ($names_where && $values_where) { - $wheres[] = "($names_where AND $values_where AND $access)"; + $wheres[] = "($names_where AND $values_where)"; } elseif ($names_where) { - $wheres[] = "($names_where AND $access)"; + $wheres[] = $names_where; } elseif ($values_where) { - $wheres[] = "($values_where AND $access)"; + $wheres[] = $values_where; } + $wheres[] = get_access_sql_suffix($table); + if ($where = implode(' AND ', $wheres)) { $return['wheres'][] = "($where)"; } diff --git a/engine/tests/api/metastrings.php b/engine/tests/api/metastrings.php index 0a8945084..cfcfb6d07 100644 --- a/engine/tests/api/metastrings.php +++ b/engine/tests/api/metastrings.php @@ -55,8 +55,11 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest { * Called after each test method. */ public function tearDown() { - // do not allow SimpleTest to interpret Elgg notices as exceptions - $this->swallowErrors(); + access_show_hidden_entities(true); + elgg_delete_annotations(array( + 'guid' => $this->object->guid, + )); + access_show_hidden_entities(false); } /** @@ -98,6 +101,31 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest { } } + public function testGetMetastringObjectFromIDWithDisabledAnnotation() { + $name = 'test_annotation_name' . rand(); + $value = 'test_annotation_value' . rand(); + $id = create_annotation($this->object->guid, $name, $value); + $annotation = elgg_get_annotation_from_id($id); + $this->assertTrue($annotation->disable()); + + $test = elgg_get_metastring_based_object_from_id($id, 'annotation'); + $this->assertEqual(false, $test); + } + + public function testGetMetastringBasedObjectWithDisabledAnnotation() { + $name = 'test_annotation_name' . rand(); + $value = 'test_annotation_value' . rand(); + $id = create_annotation($this->object->guid, $name, $value); + $annotation = elgg_get_annotation_from_id($id); + $this->assertTrue($annotation->disable()); + + $test = elgg_get_metastring_based_objects(array( + 'metastring_type' => 'annotations', + 'guid' => $this->object->guid, + )); + $this->assertEqual(array(), $test); + } + public function testEnableDisableByID() { $db_prefix = elgg_get_config('dbprefix'); $annotations = $this->createAnnotations(1); -- cgit v1.2.3 From 4c82412b8f20a17ecb87b495af5fbbc0700c28c3 Mon Sep 17 00:00:00 2001 From: cash Date: Thu, 2 May 2013 22:08:48 -0400 Subject: not sure what a flush() is doing there --- engine/tests/api/metastrings.php | 1 - 1 file changed, 1 deletion(-) (limited to 'engine/tests') diff --git a/engine/tests/api/metastrings.php b/engine/tests/api/metastrings.php index cfcfb6d07..5efdab972 100644 --- a/engine/tests/api/metastrings.php +++ b/engine/tests/api/metastrings.php @@ -147,7 +147,6 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest { // enable $ashe = access_get_show_hidden_status(); access_show_hidden_entities(true); - flush(); $this->assertTrue(elgg_set_metastring_based_object_enabled_by_id($id, 'yes', $type)); $test = get_data($q); -- cgit v1.2.3 From 4129637ba28113cea9b27a9644d51354f67e9f55 Mon Sep 17 00:00:00 2001 From: Cash Costello Date: Sat, 11 May 2013 09:59:12 -0400 Subject: Fixes #5419 adds tests for enabling/disabling annotations and fixes bug with deleting disabled annotations when deleting an entity --- engine/lib/annotations.php | 24 +++++++----- engine/lib/entities.php | 11 +++++- engine/lib/metadata.php | 13 +++---- engine/tests/api/annotations.php | 80 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 20 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index bd5ea1a1f..81755f169 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -224,7 +224,7 @@ function elgg_get_annotations(array $options = array()) { * annotation_name(s), annotation_value(s), or guid(s) must be set. * * @param array $options An options array. {@See elgg_get_annotations()} - * @return mixed Null if the metadata name is invalid. Bool on success or fail. + * @return bool|null true on success, false on failure, null if no annotations to delete. * @since 1.8.0 */ function elgg_delete_annotations(array $options) { @@ -242,7 +242,7 @@ function elgg_delete_annotations(array $options) { * @warning Unlike elgg_get_annotations() this will not accept an empty options array! * * @param array $options An options array. {@See elgg_get_annotations()} - * @return mixed + * @return bool|null true on success, false on failure, null if no annotations disabled. * @since 1.8.0 */ function elgg_disable_annotations(array $options) { @@ -259,8 +259,11 @@ function elgg_disable_annotations(array $options) { * * @warning Unlike elgg_get_annotations() this will not accept an empty options array! * + * @warning In order to enable annotations, you must first use + * {@link access_show_hidden_entities()}. + * * @param array $options An options array. {@See elgg_get_annotations()} - * @return mixed + * @return bool|null true on success, false on failure, null if no metadata enabled. * @since 1.8.0 */ function elgg_enable_annotations(array $options) { @@ -532,15 +535,16 @@ function elgg_annotation_exists($entity_guid, $annotation_type, $owner_guid = NU return FALSE; } - $entity_guid = (int)$entity_guid; - $annotation_type = sanitise_string($annotation_type); + $entity_guid = sanitize_int($entity_guid); + $owner_guid = sanitize_int($owner_guid); + $annotation_type = sanitize_string($annotation_type); - $sql = "select a.id" . - " FROM {$CONFIG->dbprefix}annotations a, {$CONFIG->dbprefix}metastrings m " . - " WHERE a.owner_guid={$owner_guid} AND a.entity_guid={$entity_guid} " . - " AND a.name_id=m.id AND m.string='{$annotation_type}'"; + $sql = "SELECT a.id FROM {$CONFIG->dbprefix}annotations a" . + " JOIN {$CONFIG->dbprefix}metastrings m ON a.name_id = m.id" . + " WHERE a.owner_guid = $owner_guid AND a.entity_guid = $entity_guid" . + " AND m.string = '$annotation_type'"; - if ($check_annotation = get_data_row($sql)) { + if (get_data_row($sql)) { return TRUE; } diff --git a/engine/lib/entities.php b/engine/lib/entities.php index cb972b282..15ab1170e 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -1619,8 +1619,8 @@ function disable_entity($guid, $reason = "", $recursive = true) { /** * Enable an entity. * - * @warning In order to enable an entity using ElggEntity::enable(), - * you must first use {@link access_show_hidden_entities()}. + * @warning In order to enable an entity, you must first use + * {@link access_show_hidden_entities()}. * * @param int $guid GUID of entity to enable * @param bool $recursive Recursively enable all entities disabled with the entity? @@ -1748,6 +1748,10 @@ function delete_entity($guid, $recursive = true) { elgg_set_ignore_access($ia); } + $entity_disable_override = access_get_show_hidden_status(); + access_show_hidden_entities(true); + $ia = elgg_set_ignore_access(true); + // Now delete the entity itself $entity->deleteMetadata(); $entity->deleteOwnedMetadata(); @@ -1755,6 +1759,9 @@ function delete_entity($guid, $recursive = true) { $entity->deleteOwnedAnnotations(); $entity->deleteRelationships(); + access_show_hidden_entities($entity_disable_override); + elgg_set_ignore_access($ia); + elgg_delete_river(array('subject_guid' => $guid)); elgg_delete_river(array('object_guid' => $guid)); remove_all_private_settings($guid); diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index ad926a49a..43f7d5d6e 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -300,10 +300,8 @@ function elgg_get_metadata(array $options = array()) { * This requires at least one constraint: metadata_owner_guid(s), * metadata_name(s), metadata_value(s), or guid(s) must be set. * - * @warning This returns null on no ops. - * * @param array $options An options array. {@see elgg_get_metadata()} - * @return mixed Null if the metadata name is invalid. Bool on success or fail. + * @return bool|null true on success, false on failure, null if no metadata to delete. * @since 1.8.0 */ function elgg_delete_metadata(array $options) { @@ -325,10 +323,8 @@ function elgg_delete_metadata(array $options) { * * @warning Unlike elgg_get_metadata() this will not accept an empty options array! * - * @warning This returns null on no ops. - * * @param array $options An options array. {@See elgg_get_metadata()} - * @return mixed + * @return bool|null true on success, false on failure, null if no metadata disabled. * @since 1.8.0 */ function elgg_disable_metadata(array $options) { @@ -347,10 +343,11 @@ function elgg_disable_metadata(array $options) { * * @warning Unlike elgg_get_metadata() this will not accept an empty options array! * - * @warning This returns null on no ops. + * @warning In order to enable metadata, you must first use + * {@link access_show_hidden_entities()}. * * @param array $options An options array. {@See elgg_get_metadata()} - * @return mixed + * @return bool|null true on success, false on failure, null if no metadata enabled. * @since 1.8.0 */ function elgg_enable_metadata(array $options) { diff --git a/engine/tests/api/annotations.php b/engine/tests/api/annotations.php index 947292970..c0b0687cc 100644 --- a/engine/tests/api/annotations.php +++ b/engine/tests/api/annotations.php @@ -65,6 +65,86 @@ class ElggCoreAnnotationAPITest extends ElggCoreUnitTest { $annotations = elgg_get_annotations($options); $this->assertTrue(empty($annotations)); + // nothing to delete so null returned + $this->assertNull(elgg_delete_annotations($options)); + + $this->assertTrue($e->delete()); + } + + public function testElggDisableAnnotations() { + $e = new ElggObject(); + $e->save(); + + for ($i=0; $i<30; $i++) { + $e->annotate('test_annotation', rand(0,10000)); + } + + $options = array( + 'guid' => $e->getGUID(), + 'limit' => 0 + ); + + $this->assertTrue(elgg_disable_annotations($options)); + + $annotations = elgg_get_annotations($options); + $this->assertTrue(empty($annotations)); + + access_show_hidden_entities(true); + $annotations = elgg_get_annotations($options); + $this->assertIdentical(30, count($annotations)); + access_show_hidden_entities(false); + + $this->assertTrue($e->delete()); + } + + public function testElggEnableAnnotations() { + $e = new ElggObject(); + $e->save(); + + for ($i=0; $i<30; $i++) { + $e->annotate('test_annotation', rand(0,10000)); + } + + $options = array( + 'guid' => $e->getGUID(), + 'limit' => 0 + ); + + $this->assertTrue(elgg_disable_annotations($options)); + + // cannot see any annotations so returns null + $this->assertNull(elgg_enable_annotations($options)); + + access_show_hidden_entities(true); + $this->assertTrue(elgg_enable_annotations($options)); + access_show_hidden_entities(false); + + $annotations = elgg_get_annotations($options); + $this->assertIdentical(30, count($annotations)); + + $this->assertTrue($e->delete()); + } + + public function testElggAnnotationExists() { + $e = new ElggObject(); + $e->save(); + $guid = $e->getGUID(); + + $this->assertFalse(elgg_annotation_exists($guid, 'test_annotation')); + + $e->annotate('test_annotation', rand(0, 10000)); + $this->assertTrue(elgg_annotation_exists($guid, 'test_annotation')); + // this metastring should always exist but an annotation of this name should not + $this->assertFalse(elgg_annotation_exists($guid, 'email')); + + $options = array( + 'guid' => $guid, + 'limit' => 0 + ); + $this->assertTrue(elgg_disable_annotations($options)); + $this->assertTrue(elgg_annotation_exists($guid, 'test_annotation')); + $this->assertTrue($e->delete()); + $this->assertFalse(elgg_annotation_exists($guid, 'test_annotation')); } } -- cgit v1.2.3 From 6fed48c68bd866149427c63782d5ce4db6ba80c4 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Mon, 13 May 2013 22:39:42 -0400 Subject: Add test for = lookbehind --- engine/tests/regression/trac_bugs.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engine/tests') diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index b7654a794..7fdd51c27 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -287,8 +287,10 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { 'web archive anchor google', 'single quotes already anchor yahoo' => - 'single quotes already anchor yahoo' + 'single quotes already anchor yahoo', + 'unquoted already anchor yahoo' => + 'unquoted already anchor yahoo', ); foreach ($cases as $input => $output) { $this->assertEqual($output, parse_urls($input)); -- cgit v1.2.3 From c7572e614606396617cb1611653f6a759be0a058 Mon Sep 17 00:00:00 2001 From: Paweł Sroka Date: Mon, 27 May 2013 05:17:08 +0200 Subject: Refs #5538 - Added regression test --- engine/tests/regression/trac_bugs.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'engine/tests') diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 7fdd51c27..180fb5112 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -296,4 +296,34 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { $this->assertEqual($output, parse_urls($input)); } } + + /** + * Checks if additional select columns does not leak to entity attributes. + * + * https://github.com/Elgg/Elgg/issues/5538 + */ + public function test_sql_selects_leak_to_attributes() { + global $ENTITY_CACHE; + //may not have groups in DB - let's create one + $group = new ElggGroup(); + $group->name = 'test_group'; + $group->access_id = ACCESS_PUBLIC; + $this->assertTrue($group->save() !== false); + + //entity cache interferes with our test + $ENTITY_CACHE = array(); + + foreach (array('site', 'user', 'group', 'object') as $type) { + $entities = elgg_get_entities(array( + 'type' => $type, + 'selects' => array('42 as added_col'), + 'limit' => 1, + )); + $entity = array_shift($entities); + $this->assertTrue($entity instanceof ElggEntity); + $this->assertEqual($entity->added_col, null, "Additional select columns are leaking to attributes for " . get_class($entity)); + } + + $group->delete(); + } } -- cgit v1.2.3 From 371e64beb9d47e0b64ce74d83a8587a73908f7d5 Mon Sep 17 00:00:00 2001 From: cash Date: Tue, 28 May 2013 18:33:55 -0400 Subject: Fixes #5531 removes symbol interpretation from translit class --- engine/classes/ElggTranslit.php | 4 ---- engine/tests/regression/trac_bugs.php | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'engine/tests') diff --git a/engine/classes/ElggTranslit.php b/engine/classes/ElggTranslit.php index 4ae1d2479..b4bf87797 100644 --- a/engine/classes/ElggTranslit.php +++ b/engine/classes/ElggTranslit.php @@ -58,10 +58,6 @@ class ElggTranslit { // currency "\xE2\x82\xAC" /* € */ => ' E ', "\xC2\xA3" /* £ */ => ' GBP ', - - "&" => ' and ', - ">" => ' greater than ', - "<" => ' less than ', )); // remove all ASCII except 0-9a-zA-Z, hyphen, underscore, and whitespace diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 7fdd51c27..051aa8d1b 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -208,12 +208,12 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { $cases = array( // acid test "B&N > Amazon, OK? 'hey!' $34" - => "b-and-n-greater-than-amazon-ok-bold-hey-34", + => "bn-amazon-ok-bold-hey-34", // hyphen, underscore and ASCII whitespace replaced by separator, // other non-alphanumeric ASCII removed - "a-a_a a\na\ra\ta\va!a\"a#a\$a%a&a'a(a)a*a+a,a.a/a:a;a=a?a@a[a\\a]a^a`a{a|a}a~a" - => "a-a-a-a-a-a-aaaaaaa-and-aaaaaaaaaaaaaaaaaaaaaaa", + "a-a_a a\na\ra\ta\va!a\"a#a\$a%aa'a(a)a*a+a,a.a/a:a;a=a?a@a[a\\a]a^a`a{a|a}a~a" + => "a-a-a-a-a-a-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", // separators trimmed "-_ hello _-" -- cgit v1.2.3 From bbf99434e13ebf304fb15a8c5b9d70c621f38c86 Mon Sep 17 00:00:00 2001 From: cash Date: Thu, 30 May 2013 21:04:09 -0400 Subject: Fixes #5564 count works with elgg_get_entities_from_annotation_calculation() --- engine/lib/annotations.php | 10 ++++++++-- engine/lib/metastrings.php | 7 +++++-- engine/tests/api/entity_getter_functions.php | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index 81755f169..124e67e0f 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -419,8 +419,8 @@ function elgg_list_entities_from_annotations($options = array()) { function elgg_get_entities_from_annotation_calculation($options) { $db_prefix = elgg_get_config('dbprefix'); $defaults = array( - 'calculation' => 'sum', - 'order_by' => 'annotation_calculation desc' + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' ); $options = array_merge($defaults, $options); @@ -457,6 +457,12 @@ function elgg_get_entities_from_annotation_calculation($options) { * @return string */ function elgg_list_entities_from_annotation_calculation($options) { + $defaults = array( + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' + ); + $options = array_merge($defaults, $options); + return elgg_list_entities($options, 'elgg_get_entities_from_annotation_calculation'); } diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index 39a81c6d0..57d876c06 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -425,7 +425,7 @@ function elgg_get_metastring_based_objects($options) { $wheres[] = get_access_sql_suffix('n_table'); } - if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) { + if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) { $selects = array_unique($selects); // evalutate selects $select_str = ''; @@ -436,6 +436,9 @@ function elgg_get_metastring_based_objects($options) { } $query = "SELECT DISTINCT n_table.*{$select_str} FROM {$db_prefix}$type n_table"; + } elseif ($options['count']) { + // count is over the entities + $query = "SELECT count(DISTINCT e.guid) as calculation FROM {$db_prefix}$type n_table"; } else { $query = "SELECT {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}$type n_table"; } @@ -464,7 +467,7 @@ function elgg_get_metastring_based_objects($options) { $defaults['order_by']); } - if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) { + if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE && !$options['count']) { if (isset($options['group_by'])) { $options['group_by'] = sanitise_string($options['group_by']); $query .= " GROUP BY {$options['group_by']}"; diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index 7bf8ef04a..0492b1fb0 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2755,7 +2755,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { 'calculation' => 'count', 'count' => true, ); - $count = (int)elgg_get_entities_from_annotation_calculation($options); + $count = elgg_get_entities_from_annotation_calculation($options); $this->assertEqual(1, $count); } -- cgit v1.2.3 From 2e979f75cd625c42ac5251140a3e7a797108f669 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sat, 1 Jun 2013 21:51:32 -0400 Subject: Add filtering for site entities, faster filtering --- engine/classes/ElggAttributeLoader.php | 30 ++++++++++++++++++++++++++++- engine/tests/regression/trac_bugs.php | 35 ++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 17 deletions(-) (limited to 'engine/tests') diff --git a/engine/classes/ElggAttributeLoader.php b/engine/classes/ElggAttributeLoader.php index b91e4b88a..0b770da75 100644 --- a/engine/classes/ElggAttributeLoader.php +++ b/engine/classes/ElggAttributeLoader.php @@ -24,7 +24,7 @@ class ElggAttributeLoader { 'time_created', 'time_updated', 'last_action', - 'enabled' + 'enabled', ); /** @@ -200,6 +200,8 @@ class ElggAttributeLoader { // saved, these are stored w/ type "site", but with no sites_entity row. These // are probably only created in the unit tests. // @todo Don't save vanilla ElggEntities with type "site" + + $row = $this->filterAddedColumns($row); $row['guid'] = (int) $row['guid']; return $row; } @@ -209,6 +211,8 @@ class ElggAttributeLoader { } } + $row = $this->filterAddedColumns($row); + // Note: If there are still missing attributes, we're running on a 1.7 or earlier schema. We let // this pass so the upgrades can run. @@ -217,4 +221,28 @@ class ElggAttributeLoader { return $row; } + + /** + * Filter out keys returned by the query which should not appear in the entity's attributes + * + * @param array $row All columns from the query + * @return array Columns acceptable for the entity's attributes + */ + protected function filterAddedColumns($row) { + // make an array with keys as acceptable attribute names + $acceptable_attrs = self::$primary_attr_names; + array_splice($acceptable_attrs, count($acceptable_attrs), 0, $this->secondary_attr_names); + $acceptable_attrs = array_combine($acceptable_attrs, $acceptable_attrs); + + // @todo remove these when #4584 is in place + $acceptable_attrs['tables_split'] = true; + $acceptable_attrs['tables_loaded'] = true; + + foreach ($row as $key => $val) { + if (!isset($acceptable_attrs[$key])) { + unset($row[$key]); + } + } + return $row; + } } diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 180fb5112..d7bb20f3b 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -297,31 +297,34 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { } } - /** - * Checks if additional select columns does not leak to entity attributes. - * - * https://github.com/Elgg/Elgg/issues/5538 - */ - public function test_sql_selects_leak_to_attributes() { + /** + * Ensure additional select columns do not end up in entity attributes. + * + * https://github.com/Elgg/Elgg/issues/5538 + */ + public function test_extra_columns_dont_appear_in_attributes() { global $ENTITY_CACHE; - //may not have groups in DB - let's create one + + // may not have groups in DB - let's create one $group = new ElggGroup(); $group->name = 'test_group'; - $group->access_id = ACCESS_PUBLIC; - $this->assertTrue($group->save() !== false); + $group->access_id = ACCESS_PUBLIC; + $this->assertTrue($group->save() !== false); - //entity cache interferes with our test + // entity cache interferes with our test $ENTITY_CACHE = array(); foreach (array('site', 'user', 'group', 'object') as $type) { $entities = elgg_get_entities(array( - 'type' => $type, - 'selects' => array('42 as added_col'), - 'limit' => 1, + 'type' => $type, + 'selects' => array('1 as _nonexistent_test_column'), + 'limit' => 1, )); - $entity = array_shift($entities); - $this->assertTrue($entity instanceof ElggEntity); - $this->assertEqual($entity->added_col, null, "Additional select columns are leaking to attributes for " . get_class($entity)); + if (!$this->assertTrue($entities, "Query for '$type' did not return an entity.")) { + continue; + } + $entity = $entities[0]; + $this->assertNull($entity->_nonexistent_test_column, "Additional select columns are leaking to attributes for '$type'"); } $group->delete(); -- cgit v1.2.3 From 50dee6fe09a1f600089b1684f6f8f91599c365a1 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sat, 1 Jun 2013 22:13:08 -0400 Subject: Refs #5538: Adds missing attributes to ElggUser and ElggCoreUserTest (by Paweł Sroka) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine/classes/ElggUser.php | 3 +++ engine/tests/objects/users.php | 3 +++ 2 files changed, 6 insertions(+) (limited to 'engine/tests') diff --git a/engine/classes/ElggUser.php b/engine/classes/ElggUser.php index 6d9f10b57..b2cada8ef 100644 --- a/engine/classes/ElggUser.php +++ b/engine/classes/ElggUser.php @@ -40,6 +40,9 @@ class ElggUser extends ElggEntity $this->attributes['code'] = NULL; $this->attributes['banned'] = "no"; $this->attributes['admin'] = 'no'; + $this->attributes['prev_last_action'] = NULL; + $this->attributes['last_login'] = NULL; + $this->attributes['prev_last_login'] = NULL; $this->attributes['tables_split'] = 2; } diff --git a/engine/tests/objects/users.php b/engine/tests/objects/users.php index a3573acb6..dc9129326 100644 --- a/engine/tests/objects/users.php +++ b/engine/tests/objects/users.php @@ -65,6 +65,9 @@ class ElggCoreUserTest extends ElggCoreUnitTest { $attributes['code'] = NULL; $attributes['banned'] = 'no'; $attributes['admin'] = 'no'; + $attributes['prev_last_action'] = NULL; + $attributes['last_login'] = NULL; + $attributes['prev_last_login'] = NULL; ksort($attributes); $entity_attributes = $this->user->expose_attributes(); -- cgit v1.2.3 From 35acc4a297de7660a191d4e7f9d3e8d55561885a Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Mon, 3 Jun 2013 17:02:33 -0400 Subject: Refs #5357: Introduces ElggBatch awareness of incomplete entities during fetch --- engine/classes/ElggBatch.php | 30 +++++++++++++++++++++------ engine/lib/entities.php | 14 ++++++++++--- engine/tests/api/helpers.php | 48 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 9 deletions(-) (limited to 'engine/tests') diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php index eb93b0f5d..34520f2bc 100644 --- a/engine/classes/ElggBatch.php +++ b/engine/classes/ElggBatch.php @@ -149,6 +149,13 @@ class ElggBatch */ private $incrementOffset = true; + /** + * Entities that could not be instantiated during a fetch + * + * @var stdClass[] + */ + private $incompleteEntities = array(); + /** * Batches operations on any elgg_get_*() or compatible function that supports * an options array. @@ -221,6 +228,17 @@ class ElggBatch } } + /** + * Tell the process that an entity was incomplete during a fetch + * + * @param stdClass $row + * + * @access private + */ + public function reportIncompleteEntity(stdClass $row) { + $this->incompleteEntities[] = $row; + } + /** * Fetches the next chunk of results * @@ -265,16 +283,16 @@ class ElggBatch $current_options = array( 'limit' => $limit, - 'offset' => $offset + 'offset' => $offset, + '__ElggBatch' => $this, ); $options = array_merge($this->options, $current_options); - $getter = $this->getter; - if (is_string($getter)) { - $this->results = $getter($options); - } else { - $this->results = call_user_func_array($getter, array($options)); + $this->incompleteEntities = array(); + $this->results = call_user_func_array($this->getter, array($options)); + if ($this->incompleteEntities) { + // @todo what to do here? } if ($this->results) { diff --git a/engine/lib/entities.php b/engine/lib/entities.php index 5cfeca6f8..b7f8c1466 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -891,6 +891,8 @@ function elgg_get_entities(array $options = array()) { 'joins' => array(), 'callback' => 'entity_row_to_elggstar', + + '__ElggBatch' => null, ); $options = array_merge($defaults, $options); @@ -1008,7 +1010,7 @@ function elgg_get_entities(array $options = array()) { } if ($options['callback'] === 'entity_row_to_elggstar') { - $dt = _elgg_fetch_entities_from_sql($query); + $dt = _elgg_fetch_entities_from_sql($query, $options['__ElggBatch']); } else { $dt = get_data($query, $options['callback']); } @@ -1043,13 +1045,14 @@ function elgg_get_entities(array $options = array()) { /** * Return entities from an SQL query generated by elgg_get_entities. * - * @param string $sql + * @param string $sql + * @param ElggBatch $batch * @return ElggEntity[] * * @access private * @throws LogicException */ -function _elgg_fetch_entities_from_sql($sql) { +function _elgg_fetch_entities_from_sql($sql, ElggBatch $batch = null) { static $plugin_subtype; if (null === $plugin_subtype) { $plugin_subtype = get_subtype_id('object', 'plugin'); @@ -1126,6 +1129,11 @@ function _elgg_fetch_entities_from_sql($sql) { } catch (IncompleteEntityException $e) { // don't let incomplete entities throw fatal errors unset($rows[$i]); + + // report incompletes to the batch process that spawned this query + if ($batch) { + $batch->reportIncompleteEntity($row); + } } } } diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 62e4471e0..753d02915 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -578,6 +578,54 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { $this->assertEqual(11, $j); } + public function testElggBatchHandlesBrokenEntities() { + $num_test_entities = 4; + $guids = array(); + $now = time(); + for ($i = $num_test_entities; $i > 0; $i--) { + $entity = new ElggObject(); + $entity->type = 'object'; + $entity->subtype = 'test_5357_subtype'; + $entity->access_id = ACCESS_PUBLIC; + $entity->time_created = ($now - $i); + $entity->save(); + $guids[] = $entity->guid; + _elgg_invalidate_cache_for_entity($entity->guid); + } + + // break the second entity + $db_prefix = elgg_get_config('dbprefix'); + delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid = {$guids[1]}"); + + $options = array( + 'type' => 'object', + 'subtype' => 'test_5357_subtype', + 'order' => 'e.time_created ASC', + ); + + $entities_visited = array(); + + $batch = new ElggBatch('elgg_get_entities', $options, null, 2); + foreach ($batch as $entity) { + $entities_visited[$entity->guid] = true; + } + + // All but the broken entity should have been visited + $this->assertEqual(count($entities_visited), $num_test_entities - 1); + + // cleanup (including leftovers from previous tests) + $entity_rows = elgg_get_entities(array_merge($options, array( + 'callback' => '', + 'limit' => false, + ))); + $guids = array(); + foreach ($entity_rows as $row) { + $guids[] = $row->guid; + } + delete_data("DELETE FROM {$db_prefix}entities WHERE guid IN (" . implode(',', $guids) . ")"); + delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")"); + } + static function elgg_batch_callback_test($options, $reset = false) { static $count = 1; -- cgit v1.2.3 From 708d2fcdc07986ee8bce5838f03f1375e8cd6d5e Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Tue, 4 Jun 2013 22:50:58 -0400 Subject: Fixes #5357: ElggBatch can now skip incomplete entities --- engine/classes/ElggBatch.php | 17 +++++++++++------ engine/tests/api/helpers.php | 19 +++++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'engine/tests') diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php index 34520f2bc..83963ccee 100644 --- a/engine/classes/ElggBatch.php +++ b/engine/classes/ElggBatch.php @@ -291,14 +291,19 @@ class ElggBatch $this->incompleteEntities = array(); $this->results = call_user_func_array($this->getter, array($options)); - if ($this->incompleteEntities) { - // @todo what to do here? - } - if ($this->results) { + // If there were incomplete entities, we pretend they were at the beginning of the results, + // fool the local counter to think it's skipped by them already, and update the running + // total as if the results contained the incompletes. + if ($this->results || $this->incompleteEntities) { $this->chunkIndex++; - $this->resultIndex = 0; - $this->retrievedResults += count($this->results); + $this->resultIndex = count($this->incompleteEntities); + $this->retrievedResults += (count($this->results) + count($this->incompleteEntities)); + if (!$this->results) { + // This fetch was *all* incompletes! We need to fetch until we can either + // offer at least one row to iterate over, or give up. + return $this->getNextResultsChunk(); + } return true; } else { return false; diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 753d02915..43244636b 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -579,7 +579,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { } public function testElggBatchHandlesBrokenEntities() { - $num_test_entities = 4; + $num_test_entities = 6; $guids = array(); $now = time(); for ($i = $num_test_entities; $i > 0; $i--) { @@ -593,25 +593,28 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { _elgg_invalidate_cache_for_entity($entity->guid); } - // break the second entity + // break entities such that the first fetch has one incomplete + // and the second fetch has only incompletes! $db_prefix = elgg_get_config('dbprefix'); - delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid = {$guids[1]}"); + delete_data(" + DELETE FROM {$db_prefix}objects_entity + WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}) + "); $options = array( 'type' => 'object', 'subtype' => 'test_5357_subtype', - 'order' => 'e.time_created ASC', + 'order_by' => 'e.time_created ASC', ); $entities_visited = array(); - $batch = new ElggBatch('elgg_get_entities', $options, null, 2); foreach ($batch as $entity) { - $entities_visited[$entity->guid] = true; + $entities_visited[] = $entity->guid; } - // All but the broken entity should have been visited - $this->assertEqual(count($entities_visited), $num_test_entities - 1); + // The broken entities should not have been visited + $this->assertEqual($entities_visited, array($guids[0], $guids[4], $guids[5])); // cleanup (including leftovers from previous tests) $entity_rows = elgg_get_entities(array_merge($options, array( -- cgit v1.2.3 From 3a3a520958e1eb31ac9d20e7cb818d8c3b5fff4a Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sat, 8 Jun 2013 21:12:03 -0400 Subject: ElggBatch with incrementOffset off now handles incomplete entities --- engine/classes/ElggBatch.php | 36 +++++++++++++++++++-------- engine/tests/api/helpers.php | 58 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 14 deletions(-) (limited to 'engine/tests') diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php index 83963ccee..ac79cf084 100644 --- a/engine/classes/ElggBatch.php +++ b/engine/classes/ElggBatch.php @@ -242,9 +242,12 @@ class ElggBatch /** * Fetches the next chunk of results * + * @param int $num_incompletes_last_fetch When called recursively, this is the number of + * incomplete entities returned in the last fetch. + * * @return bool */ - private function getNextResultsChunk() { + private function getNextResultsChunk($num_incompletes_last_fetch = 0) { // always reset results. $this->results = array(); @@ -278,7 +281,7 @@ class ElggBatch if ($this->incrementOffset) { $offset = $this->offset + $this->retrievedResults; } else { - $offset = $this->offset; + $offset = $this->offset + $num_incompletes_last_fetch; } $current_options = array( @@ -292,17 +295,30 @@ class ElggBatch $this->incompleteEntities = array(); $this->results = call_user_func_array($this->getter, array($options)); - // If there were incomplete entities, we pretend they were at the beginning of the results, - // fool the local counter to think it's skipped by them already, and update the running - // total as if the results contained the incompletes. - if ($this->results || $this->incompleteEntities) { + $num_results = count($this->results); + $num_incomplete = count($this->incompleteEntities); + + if ($this->incompleteEntities) { + // pad the front of the results with nulls representing the incompletes + array_splice($this->results, 0, 0, array_pad(array(), $num_incomplete, null)); + // ...and skip past them + reset($this->results); + for ($i = 0; $i < $num_incomplete; $i++) { + next($this->results); + } + } + + if ($this->results) { $this->chunkIndex++; - $this->resultIndex = count($this->incompleteEntities); - $this->retrievedResults += (count($this->results) + count($this->incompleteEntities)); - if (!$this->results) { + + // let the system know we've jumped past the nulls + $this->resultIndex = $num_incomplete; + + $this->retrievedResults += ($num_results + $num_incomplete); + if ($num_results == 0) { // This fetch was *all* incompletes! We need to fetch until we can either // offer at least one row to iterate over, or give up. - return $this->getNextResultsChunk(); + return $this->getNextResultsChunk($num_incomplete); } return true; } else { diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 43244636b..06ef55138 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -578,16 +578,14 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { $this->assertEqual(11, $j); } - public function testElggBatchHandlesBrokenEntities() { + public function testElggBatchReadHandlesBrokenEntities() { $num_test_entities = 6; $guids = array(); - $now = time(); for ($i = $num_test_entities; $i > 0; $i--) { $entity = new ElggObject(); $entity->type = 'object'; $entity->subtype = 'test_5357_subtype'; $entity->access_id = ACCESS_PUBLIC; - $entity->time_created = ($now - $i); $entity->save(); $guids[] = $entity->guid; _elgg_invalidate_cache_for_entity($entity->guid); @@ -604,11 +602,12 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { $options = array( 'type' => 'object', 'subtype' => 'test_5357_subtype', - 'order_by' => 'e.time_created ASC', + 'order_by' => 'e.guid', ); $entities_visited = array(); $batch = new ElggBatch('elgg_get_entities', $options, null, 2); + /* @var ElggEntity[] $batch */ foreach ($batch as $entity) { $entities_visited[] = $entity->guid; } @@ -629,6 +628,57 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")"); } + public function testElggBatchDeleteHandlesBrokenEntities() { + $num_test_entities = 6; + $guids = array(); + for ($i = $num_test_entities; $i > 0; $i--) { + $entity = new ElggObject(); + $entity->type = 'object'; + $entity->subtype = 'test_5357_subtype'; + $entity->access_id = ACCESS_PUBLIC; + $entity->save(); + $guids[] = $entity->guid; + _elgg_invalidate_cache_for_entity($entity->guid); + } + + // break entities such that the first fetch has one incomplete + // and the second fetch has only incompletes! + $db_prefix = elgg_get_config('dbprefix'); + delete_data(" + DELETE FROM {$db_prefix}objects_entity + WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}) + "); + + $options = array( + 'type' => 'object', + 'subtype' => 'test_5357_subtype', + 'order_by' => 'e.guid', + ); + + $entities_visited = array(); + $batch = new ElggBatch('elgg_get_entities', $options, null, 2, false); + /* @var ElggEntity[] $batch */ + foreach ($batch as $entity) { + $entities_visited[] = $entity->guid; + $entity->delete(); + } + + // The broken entities should not have been visited + $this->assertEqual($entities_visited, array($guids[0], $guids[4], $guids[5])); + + // cleanup (including leftovers from previous tests) + $entity_rows = elgg_get_entities(array_merge($options, array( + 'callback' => '', + 'limit' => false, + ))); + $guids = array(); + foreach ($entity_rows as $row) { + $guids[] = $row->guid; + } + delete_data("DELETE FROM {$db_prefix}entities WHERE guid IN (" . implode(',', $guids) . ")"); + delete_data("DELETE FROM {$db_prefix}objects_entity WHERE guid IN (" . implode(',', $guids) . ")"); + } + static function elgg_batch_callback_test($options, $reset = false) { static $count = 1; -- cgit v1.2.3 From 8a47b2342e53c9cdf3093982486b19d6cc2f3e9b Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sat, 8 Jun 2013 21:34:11 -0400 Subject: Improved algorithm by tracking total incomplete entities --- engine/classes/ElggBatch.php | 18 ++++++++++++------ engine/tests/api/helpers.php | 16 ++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'engine/tests') diff --git a/engine/classes/ElggBatch.php b/engine/classes/ElggBatch.php index ac79cf084..d810ea066 100644 --- a/engine/classes/ElggBatch.php +++ b/engine/classes/ElggBatch.php @@ -156,6 +156,13 @@ class ElggBatch */ private $incompleteEntities = array(); + /** + * Total number of incomplete entities fetched + * + * @var int + */ + private $totalIncompletes = 0; + /** * Batches operations on any elgg_get_*() or compatible function that supports * an options array. @@ -242,12 +249,9 @@ class ElggBatch /** * Fetches the next chunk of results * - * @param int $num_incompletes_last_fetch When called recursively, this is the number of - * incomplete entities returned in the last fetch. - * * @return bool */ - private function getNextResultsChunk($num_incompletes_last_fetch = 0) { + private function getNextResultsChunk() { // always reset results. $this->results = array(); @@ -281,7 +285,7 @@ class ElggBatch if ($this->incrementOffset) { $offset = $this->offset + $this->retrievedResults; } else { - $offset = $this->offset + $num_incompletes_last_fetch; + $offset = $this->offset + $this->totalIncompletes; } $current_options = array( @@ -298,6 +302,8 @@ class ElggBatch $num_results = count($this->results); $num_incomplete = count($this->incompleteEntities); + $this->totalIncompletes += $num_incomplete; + if ($this->incompleteEntities) { // pad the front of the results with nulls representing the incompletes array_splice($this->results, 0, 0, array_pad(array(), $num_incomplete, null)); @@ -318,7 +324,7 @@ class ElggBatch if ($num_results == 0) { // This fetch was *all* incompletes! We need to fetch until we can either // offer at least one row to iterate over, or give up. - return $this->getNextResultsChunk($num_incomplete); + return $this->getNextResultsChunk(); } return true; } else { diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 06ef55138..10216140f 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -579,7 +579,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { } public function testElggBatchReadHandlesBrokenEntities() { - $num_test_entities = 6; + $num_test_entities = 8; $guids = array(); for ($i = $num_test_entities; $i > 0; $i--) { $entity = new ElggObject(); @@ -592,11 +592,11 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { } // break entities such that the first fetch has one incomplete - // and the second fetch has only incompletes! + // and the second and third fetches have only incompletes! $db_prefix = elgg_get_config('dbprefix'); delete_data(" DELETE FROM {$db_prefix}objects_entity - WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}) + WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}, {$guids[4]}, {$guids[5]}) "); $options = array( @@ -613,7 +613,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { } // The broken entities should not have been visited - $this->assertEqual($entities_visited, array($guids[0], $guids[4], $guids[5])); + $this->assertEqual($entities_visited, array($guids[0], $guids[6], $guids[7])); // cleanup (including leftovers from previous tests) $entity_rows = elgg_get_entities(array_merge($options, array( @@ -629,7 +629,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { } public function testElggBatchDeleteHandlesBrokenEntities() { - $num_test_entities = 6; + $num_test_entities = 8; $guids = array(); for ($i = $num_test_entities; $i > 0; $i--) { $entity = new ElggObject(); @@ -642,11 +642,11 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { } // break entities such that the first fetch has one incomplete - // and the second fetch has only incompletes! + // and the second and third fetches have only incompletes! $db_prefix = elgg_get_config('dbprefix'); delete_data(" DELETE FROM {$db_prefix}objects_entity - WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}) + WHERE guid IN ({$guids[1]}, {$guids[2]}, {$guids[3]}, {$guids[4]}, {$guids[5]}) "); $options = array( @@ -664,7 +664,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { } // The broken entities should not have been visited - $this->assertEqual($entities_visited, array($guids[0], $guids[4], $guids[5])); + $this->assertEqual($entities_visited, array($guids[0], $guids[6], $guids[7])); // cleanup (including leftovers from previous tests) $entity_rows = elgg_get_entities(array_merge($options, array( -- cgit v1.2.3 From 5a1a793f8634e0f7133644e09e9ace60782864d4 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sat, 8 Jun 2013 22:12:12 -0400 Subject: Fixes #5598: Properly update metadata cache in update_metadata() --- engine/lib/metadata.php | 10 +++++----- engine/tests/api/metadata_cache.php | 7 +++++++ 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 43f7d5d6e..046b85124 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -191,19 +191,19 @@ function update_metadata($id, $name, $value, $value_type, $owner_guid, $access_i } // Add the metastring - $value = add_metastring($value); - if (!$value) { + $value_id = add_metastring($value); + if (!$value_id) { return false; } - $name = add_metastring($name); - if (!$name) { + $name_id = add_metastring($name); + if (!$name_id) { return false; } // If ok then add it $query = "UPDATE {$CONFIG->dbprefix}metadata" - . " set name_id='$name', value_id='$value', value_type='$value_type', access_id=$access_id," + . " set name_id='$name_id', value_id='$value_id', value_type='$value_type', access_id=$access_id," . " owner_guid=$owner_guid where id=$id"; $result = update_data($query); diff --git a/engine/tests/api/metadata_cache.php b/engine/tests/api/metadata_cache.php index 846116a7b..7fb328169 100644 --- a/engine/tests/api/metadata_cache.php +++ b/engine/tests/api/metadata_cache.php @@ -166,4 +166,11 @@ class ElggCoreMetadataCacheTest extends ElggCoreUnitTest { $actual = $this->cache->filterMetadataHeavyEntities($guids, 6000); $this->assertIdentical($actual, $expected); } + + public function testCreateMetadataInvalidates() { + $this->obj1->foo = 1; + create_metadata($this->guid1, 'foo', 2, '', elgg_get_logged_in_user_guid(), ACCESS_FRIENDS); + + $this->assertEqual($this->obj1->foo, 2); + } } -- cgit v1.2.3 From 9892692deefdb06d9e7176c72fc5780ab79e3a7d Mon Sep 17 00:00:00 2001 From: Brett Profitt Date: Tue, 9 Jul 2013 12:13:17 -0400 Subject: Fixes #5706. Allowing parens in URIs if not last character. --- engine/lib/output.php | 8 ++++---- engine/tests/regression/trac_bugs.php | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/output.php b/engine/lib/output.php index 5adc01053..6172a5c8d 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -27,16 +27,16 @@ function parse_urls($text) { // By default htmlawed rewrites tags to this format. // if PHP supported conditional negative lookbehinds we could use this: // $r = preg_replace_callback('/(?"\'\!\(\),]+)/i', - $r = preg_replace_callback('/(?"\'\(\)]+)/i', + $r = preg_replace_callback('/(?"\']+)/i', create_function( '$matches', ' $url = $matches[1]; - $punc = \'\'; + $punc = ""; $last = substr($url, -1, 1); - if (in_array($last, array(".", "!", ","))) { + if (in_array($last, array(".", "!", ",", "(", ")"))) { $punc = $last; - $url = rtrim($url, ".!,"); + $url = rtrim($url, ".!,()"); } $urltext = str_replace("/", "/", $url); return "$urltext$punc"; diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 5730830bb..f173b5b9f 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -291,6 +291,9 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { 'unquoted already anchor yahoo' => 'unquoted already anchor yahoo', + + 'parens in uri http://thedailywtf.com/Articles/A-(Long-Overdue)-BuildMaster-Introduction.aspx' => + 'parens in uri http://thedailywtf.com/Articles/A-(Long-Overdue)-BuildMaster-Introduction.aspx' ); foreach ($cases as $input => $output) { $this->assertEqual($output, parse_urls($input)); -- cgit v1.2.3 From 49ab3a17173aedb8b5e3a2a228cc6cfd0a510e49 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Fri, 20 Sep 2013 21:19:06 -0400 Subject: Test that get_user_by_username accepts URL encoded input --- engine/tests/objects/users.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'engine/tests') diff --git a/engine/tests/objects/users.php b/engine/tests/objects/users.php index dc9129326..7d2ef6961 100644 --- a/engine/tests/objects/users.php +++ b/engine/tests/objects/users.php @@ -159,6 +159,22 @@ class ElggCoreUserTest extends ElggCoreUnitTest { $this->assertFalse($user); } + public function testGetUserByUsernameAcceptsUrlEncoded() { + $username = (string)time(); + $this->user->username = $username; + $guid = $this->user->save(); + + // percent encode first letter + $first_letter = $username[0]; + $first_letter = str_pad('%' . dechex(ord($first_letter)), 2, '0', STR_PAD_LEFT); + $username = $first_letter . substr($username, 1); + + $user = get_user_by_username($username); + $this->assertTrue((bool) $user); + $this->assertEqual($guid, $user->guid); + + $this->user->delete(); + } public function testElggUserMakeAdmin() { global $CONFIG; -- cgit v1.2.3 From 5a3095d0664dc8c1fa81c7c2e6fac6a8dc8f0eaf Mon Sep 17 00:00:00 2001 From: Jerome Bakker Date: Tue, 22 Oct 2013 14:35:38 +0200 Subject: fixed a unittest I broke in #398 --- engine/tests/api/entity_getter_functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engine/tests') diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index 0492b1fb0..fef9dc0c5 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -426,7 +426,7 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { $options = array( 'types' => $types, - 'subtype' => $subtype + 'subtypes' => $subtype ); $es = elgg_get_entities($options); -- cgit v1.2.3 From 424eff09557bf5e0cee7f0c1a717b3992d2e82ac Mon Sep 17 00:00:00 2001 From: Jerome Bakker Date: Wed, 23 Oct 2013 15:35:05 +0200 Subject: replaced all references to trac.elgg.org to the correct GitHub issues --- documentation/info/manifest.xml | 2 +- engine/classes/ElggAttributeLoader.php | 12 ++++++------ engine/classes/ElggEntity.php | 12 ++++++------ engine/lib/database.php | 12 ++++++------ engine/lib/entities.php | 2 +- engine/lib/upgrade.php | 2 +- engine/lib/upgrades/2010033101.php | 2 +- ...012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php | 2 +- engine/lib/views.php | 2 +- engine/tests/api/helpers.php | 2 +- engine/tests/api/metadata.php | 2 +- engine/tests/api/plugins.php | 4 ++-- engine/tests/objects/entities.php | 2 +- engine/tests/objects/objects.php | 2 +- engine/tests/regression/trac_bugs.php | 10 +++++----- engine/tests/test_files/plugin_18/manifest.xml | 2 +- mod/search/README.txt | 2 +- upgrade.php | 2 +- views/default/js/elgg.php | 2 +- 19 files changed, 39 insertions(+), 39 deletions(-) (limited to 'engine/tests') diff --git a/documentation/info/manifest.xml b/documentation/info/manifest.xml index 494158481..4fd4be8ce 100644 --- a/documentation/info/manifest.xml +++ b/documentation/info/manifest.xml @@ -7,7 +7,7 @@ This is a longer, more interesting description of my plugin, its features, and other important information. http://www.elgg.org/ https://github.com/Elgg/Elgg - http://trac.elgg.org + https://github.com/Elgg/Elgg/issues http://elgg.org/supporter.php (C) Elgg 2011 GNU General Public License version 2 diff --git a/engine/classes/ElggAttributeLoader.php b/engine/classes/ElggAttributeLoader.php index 0b770da75..ffc80b02d 100644 --- a/engine/classes/ElggAttributeLoader.php +++ b/engine/classes/ElggAttributeLoader.php @@ -4,7 +4,7 @@ * Loads ElggEntity attributes from DB or validates those passed in via constructor * * @access private - * + * * @package Elgg.Core * @subpackage DataModel */ @@ -69,7 +69,7 @@ class ElggAttributeLoader { /** * Constructor - * + * * @param string $class class of object being loaded * @param string $required_type entity type this is being used to populate * @param array $initialized_attrs attributes after initializeAttributes() has been run @@ -94,7 +94,7 @@ class ElggAttributeLoader { /** * Get primary attributes missing that are missing - * + * * @param stdClass $row Database row * @return array */ @@ -104,7 +104,7 @@ class ElggAttributeLoader { /** * Get secondary attributes that are missing - * + * * @param stdClass $row Database row * @return array */ @@ -114,7 +114,7 @@ class ElggAttributeLoader { /** * Check that the type is correct - * + * * @param stdClass $row Database row * @return void * @throws InvalidClassException @@ -216,7 +216,7 @@ class ElggAttributeLoader { // Note: If there are still missing attributes, we're running on a 1.7 or earlier schema. We let // this pass so the upgrades can run. - // guid needs to be an int http://trac.elgg.org/ticket/4111 + // guid needs to be an int https://github.com/elgg/elgg/issues/4111 $row['guid'] = (int) $row['guid']; return $row; diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index dd1c7c114..a563f6fad 100644 --- a/engine/classes/ElggEntity.php +++ b/engine/classes/ElggEntity.php @@ -24,7 +24,7 @@ * * @package Elgg.Core * @subpackage DataModel.Entities - * + * * @property string $type object, user, group, or site (read-only after save) * @property string $subtype Further clarifies the nature of the entity (read-only after save) * @property int $guid The unique identifier for this entity (read only) @@ -352,8 +352,8 @@ abstract class ElggEntity extends ElggData implements 'limit' => 0 ); // @todo in 1.9 make this return false if can't add metadata - // http://trac.elgg.org/ticket/4520 - // + // https://github.com/elgg/elgg/issues/4520 + // // need to remove access restrictions right now to delete // because this is the expected behavior $ia = elgg_set_ignore_access(true); @@ -379,7 +379,7 @@ abstract class ElggEntity extends ElggData implements // unsaved entity. store in temp array // returning single entries instead of an array of 1 element is decided in // getMetaData(), just like pulling from the db. - // + // // if overwrite, delete first if (!$multiple || !isset($this->temp_metadata[$name])) { $this->temp_metadata[$name] = array(); @@ -964,7 +964,7 @@ abstract class ElggEntity extends ElggData implements * * @tip Can be overridden by registering for the permissions_check:comment, * plugin hook. - * + * * @param int $user_guid User guid (default is logged in user) * * @return bool @@ -1365,7 +1365,7 @@ abstract class ElggEntity extends ElggData implements $this->attributes['tables_loaded']++; } - // guid needs to be an int http://trac.elgg.org/ticket/4111 + // guid needs to be an int https://github.com/elgg/elgg/issues/4111 $this->attributes['guid'] = (int)$this->attributes['guid']; // Cache object handle diff --git a/engine/lib/database.php b/engine/lib/database.php index 37dfb8f8d..a7949788d 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -129,7 +129,7 @@ function establish_db_link($dblinkname = "readwrite") { // Set up cache if global not initialized and query cache not turned off if ((!$DB_QUERY_CACHE) && (!$db_cache_off)) { // @todo if we keep this cache in 1.9, expose the size as a config parameter - $DB_QUERY_CACHE = new ElggLRUCache(200); + $DB_QUERY_CACHE = new ElggLRUCache(200); } } @@ -399,14 +399,14 @@ function elgg_query_runner($query, $callback = null, $single = false) { // Since we want to cache results of running the callback, we need to // need to namespace the query with the callback and single result request. - // http://trac.elgg.org/ticket/4049 + // https://github.com/elgg/elgg/issues/4049 $hash = (string)$callback . (int)$single . $query; // Is cached? if ($DB_QUERY_CACHE) { if (isset($DB_QUERY_CACHE[$hash])) { elgg_log("DB query $query results returned from cache (hash: $hash)", 'NOTICE'); - return $DB_QUERY_CACHE[$hash]; + return $DB_QUERY_CACHE[$hash]; } } @@ -524,7 +524,7 @@ function delete_data($query) { /** * Invalidate the query cache - * + * * @access private */ function _elgg_invalidate_query_cache() { @@ -533,7 +533,7 @@ function _elgg_invalidate_query_cache() { $DB_QUERY_CACHE->clear(); elgg_log("Query cache invalidated", 'NOTICE'); } elseif ($DB_QUERY_CACHE) { - // In case someone sets the cache to an array and primes it with data + // In case someone sets the cache to an array and primes it with data $DB_QUERY_CACHE = array(); elgg_log("Query cache invalidated", 'NOTICE'); } @@ -668,7 +668,7 @@ function run_sql_script($scriptlocation) { /** * Format a query string for logging - * + * * @param string $query Query string * @return string * @access private diff --git a/engine/lib/entities.php b/engine/lib/entities.php index 997db79d2..4fcf1c657 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -791,7 +791,7 @@ function get_entity($guid) { if ($shared_cache) { $cached_entity = $shared_cache->load($guid); - // @todo store ACLs in memcache http://trac.elgg.org/ticket/3018#comment:3 + // @todo store ACLs in memcache https://github.com/elgg/elgg/issues/3018#issuecomment-13662617 if ($cached_entity) { // @todo use ACL and cached entity access_id to determine if user can see it return $cached_entity; diff --git a/engine/lib/upgrade.php b/engine/lib/upgrade.php index 0cc1e64dc..158ec9ec1 100644 --- a/engine/lib/upgrade.php +++ b/engine/lib/upgrade.php @@ -245,7 +245,7 @@ function version_upgrade() { // No version number? Oh snap...this is an upgrade from a clean installation < 1.7. // Run all upgrades without error reporting and hope for the best. - // See http://trac.elgg.org/elgg/ticket/1432 for more. + // See https://github.com/elgg/elgg/issues/1432 for more. $quiet = !$dbversion; // Note: Database upgrades are deprecated as of 1.8. Use code upgrades. See #1433 diff --git a/engine/lib/upgrades/2010033101.php b/engine/lib/upgrades/2010033101.php index 0bffee001..4779295fd 100644 --- a/engine/lib/upgrades/2010033101.php +++ b/engine/lib/upgrades/2010033101.php @@ -1,7 +1,7 @@ container_guid); diff --git a/engine/tests/api/helpers.php b/engine/tests/api/helpers.php index 10216140f..414fb4145 100644 --- a/engine/tests/api/helpers.php +++ b/engine/tests/api/helpers.php @@ -519,7 +519,7 @@ class ElggCoreHelpersTest extends ElggCoreUnitTest { $this->assertIdentical($elements_sorted_string, $test_elements); } - // see http://trac.elgg.org/ticket/4288 + // see https://github.com/elgg/elgg/issues/4288 public function testElggBatchIncOffset() { // normal increment $options = array( diff --git a/engine/tests/api/metadata.php b/engine/tests/api/metadata.php index 0862341c1..d23510c6a 100644 --- a/engine/tests/api/metadata.php +++ b/engine/tests/api/metadata.php @@ -139,7 +139,7 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest { // Make sure metadata with multiple values is correctly deleted when re-written // by another user - // http://trac.elgg.org/ticket/2776 + // https://github.com/elgg/elgg/issues/2776 public function test_elgg_metadata_multiple_values() { $u1 = new ElggUser(); $u1->username = rand(); diff --git a/engine/tests/api/plugins.php b/engine/tests/api/plugins.php index 114f3991b..d0f111c48 100644 --- a/engine/tests/api/plugins.php +++ b/engine/tests/api/plugins.php @@ -69,7 +69,7 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest { 'description' => 'A longer, more interesting description.', 'website' => 'http://www.elgg.org/', 'repository' => 'https://github.com/Elgg/Elgg', - 'bugtracker' => 'http://trac.elgg.org', + 'bugtracker' => 'https://github.com/elgg/elgg/issues', 'donations' => 'http://elgg.org/supporter.php', 'copyright' => '(C) Elgg Foundation 2011', 'license' => 'GNU General Public License version 2', @@ -174,7 +174,7 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest { } public function testElggPluginManifestGetBugtracker() { - $this->assertEqual($this->manifest18->getBugTrackerURL(), 'http://trac.elgg.org'); + $this->assertEqual($this->manifest18->getBugTrackerURL(), 'https://github.com/elgg/elgg/issues'); $this->assertEqual($this->manifest17->getBugTrackerURL(), ''); } diff --git a/engine/tests/objects/entities.php b/engine/tests/objects/entities.php index 248b85c9e..bac72079e 100644 --- a/engine/tests/objects/entities.php +++ b/engine/tests/objects/entities.php @@ -271,7 +271,7 @@ class ElggCoreEntityTest extends ElggCoreUnitTest { $this->save_entity(); // test deleting incorrectly - // @link http://trac.elgg.org/ticket/2273 + // @link https://github.com/elgg/elgg/issues/2273 $this->assertNull($this->entity->deleteMetadata('impotent')); $this->assertEqual($this->entity->important, 'indeed!'); diff --git a/engine/tests/objects/objects.php b/engine/tests/objects/objects.php index 915594e0a..263ab2414 100644 --- a/engine/tests/objects/objects.php +++ b/engine/tests/objects/objects.php @@ -194,7 +194,7 @@ class ElggCoreObjectTest extends ElggCoreUnitTest { $old = elgg_set_ignore_access(true); } - // see http://trac.elgg.org/ticket/1196 + // see https://github.com/elgg/elgg/issues/1196 public function testElggEntityRecursiveDisableWhenLoggedOut() { $e1 = new ElggObject(); $e1->access_id = ACCESS_PUBLIC; diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index f173b5b9f..9372b0855 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -201,8 +201,8 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { } /** - * http://trac.elgg.org/ticket/3210 - Don't remove -s in friendly titles - * http://trac.elgg.org/ticket/2276 - improve char encoding + * https://github.com/elgg/elgg/issues/3210 - Don't remove -s in friendly titles + * https://github.com/elgg/elgg/issues/2276 - improve char encoding */ public function test_friendly_title() { $cases = array( @@ -216,7 +216,7 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { => "a-a-a-a-a-a-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", // separators trimmed - "-_ hello _-" + "-_ hello _-" => "hello", // accents removed, lower case, other multibyte chars are URL encoded @@ -286,7 +286,7 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { 'web archive anchor google' => 'web archive anchor google', - 'single quotes already anchor yahoo' => + 'single quotes already anchor yahoo' => 'single quotes already anchor yahoo', 'unquoted already anchor yahoo' => @@ -302,7 +302,7 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { /** * Ensure additional select columns do not end up in entity attributes. - * + * * https://github.com/Elgg/Elgg/issues/5538 */ public function test_extra_columns_dont_appear_in_attributes() { diff --git a/engine/tests/test_files/plugin_18/manifest.xml b/engine/tests/test_files/plugin_18/manifest.xml index 5d788616a..c8b407511 100644 --- a/engine/tests/test_files/plugin_18/manifest.xml +++ b/engine/tests/test_files/plugin_18/manifest.xml @@ -7,7 +7,7 @@ A longer, more interesting description. http://www.elgg.org/ https://github.com/Elgg/Elgg - http://trac.elgg.org + https://github.com/elgg/elgg/issues http://elgg.org/supporter.php (C) Elgg Foundation 2011 GNU General Public License version 2 diff --git a/mod/search/README.txt b/mod/search/README.txt index 98a002dd5..ac5930e5f 100644 --- a/mod/search/README.txt +++ b/mod/search/README.txt @@ -273,4 +273,4 @@ MySQL's fulltext engine returns *ZERO* rows if more than 50% of the rows searched match. The default search hooks for users and groups ignore subtypes. -See [trac ticket 1499](http://trac.elgg.org/elgg/ticket/1499) +See [GitHub issue 1499](https://github.com/elgg/elgg/issues/1499) diff --git a/upgrade.php b/upgrade.php index c5f158c61..d07b2a1da 100644 --- a/upgrade.php +++ b/upgrade.php @@ -46,7 +46,7 @@ if (get_input('upgrade') == 'upgrade') { } else { // if upgrading from < 1.8.0, check for the core view 'welcome' and bail if it's found. - // see http://trac.elgg.org/ticket/3064 + // see https://github.com/elgg/elgg/issues/3064 // we're not checking the view itself because it's likely themes will override this view. // we're only concerned with core files. $welcome = dirname(__FILE__) . '/views/default/welcome.php'; diff --git a/views/default/js/elgg.php b/views/default/js/elgg.php index 6fe03484d..c3b56e398 100644 --- a/views/default/js/elgg.php +++ b/views/default/js/elgg.php @@ -43,7 +43,7 @@ $libs = array( foreach ($libs as $file) { include("{$CONFIG->path}js/lib/$file.js"); - // putting a new line between the files to address http://trac.elgg.org/ticket/3081 + // putting a new line between the files to address https://github.com/elgg/elgg/issues/3081 echo "\n"; } -- cgit v1.2.3 From 0deb80da1e82af55bf8d7500d09b36225ddd7927 Mon Sep 17 00:00:00 2001 From: Jerome Bakker Date: Wed, 23 Oct 2013 16:03:08 +0200 Subject: found some more references to trac --- engine/lib/elgglib.php | 4 ++-- engine/lib/views.php | 4 ++-- engine/tests/objects/users.php | 2 +- engine/tests/regression/trac_bugs.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'engine/tests') diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index b5ef7e572..c95e0c28c 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -1350,7 +1350,7 @@ function full_url() { "" : (":" . $_SERVER["SERVER_PORT"]); // This is here to prevent XSS in poorly written browsers used by 80% of the population. - // {@trac [5813]} + // https://github.com/Elgg/Elgg/commit/0c947e80f512cb0a482b1864fd0a6965c8a0cd4a $quotes = array('\'', '"'); $encoded = array('%27', '%22'); @@ -2249,7 +2249,7 @@ function elgg_api_test($hook, $type, $value, $params) { * * @warning ACCESS_DEFAULT is a place holder for the input/access view. Do not * use it when saving an entity. - * + * * @var int */ define('ACCESS_DEFAULT', -1); diff --git a/engine/lib/views.php b/engine/lib/views.php index dc69395c6..fff3581cf 100644 --- a/engine/lib/views.php +++ b/engine/lib/views.php @@ -369,7 +369,7 @@ function elgg_view_exists($view, $viewtype = '', $recurse = true) { * view, $view_name plugin hook. * * @warning Any variables in $_SESSION will override passed vars - * upon name collision. See {@trac #2124}. + * upon name collision. See https://github.com/Elgg/Elgg/issues/2124 * * @param string $view The name and location of the view to use * @param array $vars Variables to pass to the view. @@ -795,7 +795,7 @@ function elgg_view_menu($menu_name, array $vars = array()) { * - bool 'full_view' Whether to show a full or condensed view. * * @tip This function can automatically appends annotations to entities if in full - * view and a handler is registered for the entity:annotate. See {@trac 964} and + * view and a handler is registered for the entity:annotate. See https://github.com/Elgg/Elgg/issues/964 and * {@link elgg_view_entity_annotations()}. * * @param ElggEntity $entity The entity to display diff --git a/engine/tests/objects/users.php b/engine/tests/objects/users.php index 7d2ef6961..8a1033ac4 100644 --- a/engine/tests/objects/users.php +++ b/engine/tests/objects/users.php @@ -145,7 +145,7 @@ class ElggCoreUserTest extends ElggCoreUnitTest { } public function testElggUserNameCache() { - // Trac #1305 + // issue https://github.com/elgg/elgg/issues/1305 // very unlikely a user would have this username $name = (string)time(); diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 9372b0855..f823825ab 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -1,7 +1,7 @@ Date: Sun, 27 Oct 2013 12:17:05 +0100 Subject: Refs #5952 - Added test --- engine/tests/regression/trac_bugs.php | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'engine/tests') diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index f823825ab..ef1348cf6 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -332,4 +332,45 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { $group->delete(); } + + /** + * Ensure that ElggBatch doesn't go into infinite loop when disabling annotations recursively when show hidden is enabled. + * + * https://github.com/Elgg/Elgg/issues/5952 + */ + public function test_disabling_annotations_infinite_loop() { + + //let's have some entity + $group = new ElggGroup(); + $group->name = 'test_group'; + $group->access_id = ACCESS_PUBLIC; + $this->assertTrue($group->save() !== false); + + $total = 51; + //add some annotations + for ($cnt = 0; $cnt < $total; $cnt++) { + $group->annotate('test_annotation', 'value_' . $total); + } + + //disable them + $show_hidden = access_get_show_hidden_status(); + access_show_hidden_entities(true); + $options = array( + 'guid' => $group->guid, + 'limit' => $total, //using strict limit to avoid real infinite loop and just see ElggBatch limiting on it before finishing the work + ); + elgg_disable_annotations($options); + access_show_hidden_entities($show_hidden); + + //confirm all being disabled + $annotations = $group->getAnnotations(array( + 'limit' => $total, + )); + foreach ($annotations as $annotation) { + $this->assertTrue($annotation->enabled == 'no'); + } + + //delete group and annotations + $group->delete(); + } } -- cgit v1.2.3 From d53447f7e6b3277f3249d9a70e56ec01a90c3a60 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Thu, 11 Jul 2013 13:24:01 -0400 Subject: Disable loading external entities during XML parsing --- engine/classes/ElggAutoP.php | 14 ++++++++++++++ engine/classes/ElggXMLElement.php | 8 ++++++-- engine/tests/regression/trac_bugs.php | 10 ++++++++++ engine/tests/test_files/xxe/external_entity.txt | 1 + engine/tests/test_files/xxe/request.xml | 8 ++++++++ 5 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 engine/tests/test_files/xxe/external_entity.txt create mode 100644 engine/tests/test_files/xxe/request.xml (limited to 'engine/tests') diff --git a/engine/classes/ElggAutoP.php b/engine/classes/ElggAutoP.php index 71536c433..05842d1b2 100644 --- a/engine/classes/ElggAutoP.php +++ b/engine/classes/ElggAutoP.php @@ -110,12 +110,19 @@ class ElggAutoP { // http://www.php.net/manual/en/domdocument.loadhtml.php#95463 libxml_use_internal_errors(true); + // Do not load entities. May be unnecessary, better safe than sorry + $disable_load_entities = libxml_disable_entity_loader(true); + if (!$this->_doc->loadHTML("{$html}" . "")) { + + libxml_disable_entity_loader($disable_load_entities); return false; } + libxml_disable_entity_loader($disable_load_entities); + $this->_xpath = new DOMXPath($this->_doc); // start processing recursively at the BODY element $nodeList = $this->_xpath->query('//body[1]'); @@ -135,9 +142,16 @@ class ElggAutoP { // re-parse so we can handle new AUTOP elements + // Do not load entities. May be unnecessary, better safe than sorry + $disable_load_entities = libxml_disable_entity_loader(true); + if (!$this->_doc->loadHTML($html)) { + libxml_disable_entity_loader($disable_load_entities); return false; } + + libxml_disable_entity_loader($disable_load_entities); + // must re-create XPath object after DOM load $this->_xpath = new DOMXPath($this->_doc); diff --git a/engine/classes/ElggXMLElement.php b/engine/classes/ElggXMLElement.php index 6f2633e25..cbd3fc5ce 100644 --- a/engine/classes/ElggXMLElement.php +++ b/engine/classes/ElggXMLElement.php @@ -20,7 +20,12 @@ class ElggXMLElement { if ($xml instanceof SimpleXMLElement) { $this->_element = $xml; } else { + // do not load entities + $disable_load_entities = libxml_disable_entity_loader(true); + $this->_element = new SimpleXMLElement($xml); + + libxml_disable_entity_loader($disable_load_entities); } } @@ -123,5 +128,4 @@ class ElggXMLElement { } return false; } - -} \ No newline at end of file +} diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index ef1348cf6..e6773c8af 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -373,4 +373,14 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { //delete group and annotations $group->delete(); } + + public function test_ElggXMLElement_does_not_load_external_entities() { + $payload = file_get_contents(dirname(dirname(__FILE__)) . '/test_files/xxe/request.xml'); + $payload = sprintf($payload, 'file://' . realpath(dirname(dirname(__FILE__)) . '/test_files/xxe/external_entity.txt')); + + $el = new ElggXMLElement($payload); + $chidren = $el->getChildren(); + $content = $chidren[0]->getContent(); + $this->assertNoPattern('/secret/', $content); + } } diff --git a/engine/tests/test_files/xxe/external_entity.txt b/engine/tests/test_files/xxe/external_entity.txt new file mode 100644 index 000000000..536aca34d --- /dev/null +++ b/engine/tests/test_files/xxe/external_entity.txt @@ -0,0 +1 @@ +secret \ No newline at end of file diff --git a/engine/tests/test_files/xxe/request.xml b/engine/tests/test_files/xxe/request.xml new file mode 100644 index 000000000..4390f9db2 --- /dev/null +++ b/engine/tests/test_files/xxe/request.xml @@ -0,0 +1,8 @@ + + + +]> + + test&xxe;test + -- cgit v1.2.3 From 6eec301f33ff3e618d591d429de7edf30277e972 Mon Sep 17 00:00:00 2001 From: Paweł Sroka Date: Tue, 23 Jul 2013 08:28:30 +0200 Subject: Enhanced test --- engine/tests/regression/trac_bugs.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'engine/tests') diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index e6773c8af..ea39253df 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -375,12 +375,26 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { } public function test_ElggXMLElement_does_not_load_external_entities() { + $elLast = libxml_disable_entity_loader(false); + $payload = file_get_contents(dirname(dirname(__FILE__)) . '/test_files/xxe/request.xml'); - $payload = sprintf($payload, 'file://' . realpath(dirname(dirname(__FILE__)) . '/test_files/xxe/external_entity.txt')); + $path = realpath(dirname(dirname(__FILE__)) . '/test_files/xxe/external_entity.txt'); + $path = str_replace('\\', '/', $path); + if ($path[0] != '/') { + $path = '/' . $path; + } + $path = 'file://' . $path; + $payload = sprintf($payload, $path); $el = new ElggXMLElement($payload); $chidren = $el->getChildren(); $content = $chidren[0]->getContent(); $this->assertNoPattern('/secret/', $content); + + //make sure the test is valid + $element = new SimpleXMLElement($payload); + $this->assertPattern('/secret/', (string)$element->methodName); + + libxml_disable_entity_loader($elLast); } } -- cgit v1.2.3 From 7cacdc8bc26c98a58dc8986acfd911d6542608af Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Wed, 31 Jul 2013 13:34:55 -0400 Subject: Emit notice if XXE can't be tested and skip test --- engine/tests/regression/trac_bugs.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'engine/tests') diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index ea39253df..689275661 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -377,6 +377,7 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { public function test_ElggXMLElement_does_not_load_external_entities() { $elLast = libxml_disable_entity_loader(false); + // build payload that should trigger loading of external entity $payload = file_get_contents(dirname(dirname(__FILE__)) . '/test_files/xxe/request.xml'); $path = realpath(dirname(dirname(__FILE__)) . '/test_files/xxe/external_entity.txt'); $path = str_replace('\\', '/', $path); @@ -384,16 +385,20 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { $path = '/' . $path; } $path = 'file://' . $path; - $payload = sprintf($payload, $path); + $payload = sprintf($payload, $path); - $el = new ElggXMLElement($payload); - $chidren = $el->getChildren(); - $content = $chidren[0]->getContent(); - $this->assertNoPattern('/secret/', $content); - - //make sure the test is valid + // make sure we can actually this in this environment $element = new SimpleXMLElement($payload); - $this->assertPattern('/secret/', (string)$element->methodName); + $can_load_entity = preg_match('/secret/', (string)$element->methodName); + + $this->skipUnless($can_load_entity, "XXE vulnerability cannot be tested on this system"); + + if ($can_load_entity) { + $el = new ElggXMLElement($payload); + $chidren = $el->getChildren(); + $content = $chidren[0]->getContent(); + $this->assertNoPattern('/secret/', $content); + } libxml_disable_entity_loader($elLast); } -- cgit v1.2.3