diff options
48 files changed, 663 insertions, 129 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index b502b8411..7a3422d7d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,48 @@ +Version 1.8.8 +(July 11, 2012 from https://github.com/Elgg/Elgg/tree/1.8) + + Contributing Developers: + * Cash Costello + * Miguel Rodriguez + * Sem + + Enhancements: + * Added a delete button on river items for admins + + Bugfixes: + * Fixed the significant bug with htmlawed plugin that caused duplicate tags + + +Version 1.8.7 +(July 10, 2012 from https://github.com/Elgg/Elgg/tree/1.8) + + Contributing Developers: + * Cash Costello + * Evan Winslow + * Ismayil Khayredinov + * Jeroen Dalsem + * Jerome Bakker + * Matt Beckett + * Miguel Rodriguez + * Paweł Sroka + * Sem + * Steve Clay + + Enhancements: + * Better support for search engine friendly URLs + * Upgraded htmlawed (XSS filtering) + * Internationalization support for TinyMCE + * Public access not available for walled gardens + * Better forwarding and messages when they cannot view content because logged out + + Bugfixes: + * Fatal errors due to type hints downgraded to warnings + * Group discussion reply notifications work again + * Sending user to inbox when deleting a message + * Fixed location profile information when it is an array + * Over 30 other bug fixes. + + Version 1.8.6 (June 18, 2012 from https://github.com/Elgg/Elgg/tree/1.8) diff --git a/actions/admin/plugins/activate.php b/actions/admin/plugins/activate.php index 286cf5a4f..5234a4ca5 100644 --- a/actions/admin/plugins/activate.php +++ b/actions/admin/plugins/activate.php @@ -47,7 +47,8 @@ if (count($activated_guids) === 1) { $url .= "?$query"; } $plugin = get_entity($plugin_guids[0]); - forward("$url#{$plugin->getID()}"); + $id = $css_id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getID()); + forward("$url#$id"); } else { // forward to top of page with a failure so remove any #foo $url = $_SERVER['HTTP_REFERER']; diff --git a/actions/admin/plugins/deactivate.php b/actions/admin/plugins/deactivate.php index e7ce65625..354f4717d 100644 --- a/actions/admin/plugins/deactivate.php +++ b/actions/admin/plugins/deactivate.php @@ -46,7 +46,8 @@ if (count($plugin_guids) == 1) { $url .= "?$query"; } $plugin = get_entity($plugin_guids[0]); - forward("$url#{$plugin->getID()}"); + $id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getID()); + forward("$url#$id"); } else { forward(REFERER); } diff --git a/actions/river/delete.php b/actions/river/delete.php new file mode 100644 index 000000000..0d8297932 --- /dev/null +++ b/actions/river/delete.php @@ -0,0 +1,21 @@ +<?php +/** + * River item delete action + * + * @package Elgg + * @subpackage Core + */ + +$id = get_input('id', false); + +if ($id !== false && elgg_is_admin_logged_in()) { + if (elgg_delete_river(array('id' => $id))) { + system_message(elgg_echo('river:delete:success')); + } else { + register_error(elgg_echo('river:delete:fail')); + } +} else { + register_error(elgg_echo('river:delete:fail')); +} + +forward(REFERER); diff --git a/engine/classes/ElggPluginManifest.php b/engine/classes/ElggPluginManifest.php index 7e79c15c8..6b3932b32 100644 --- a/engine/classes/ElggPluginManifest.php +++ b/engine/classes/ElggPluginManifest.php @@ -456,7 +456,7 @@ class ElggPluginManifest { * Normalizes a dependency array using the defined structs. * Can be used with either requires or suggests. * - * @param array $dep An dependency array. + * @param array $dep A dependency array. * @return array The normalized deps array. */ private function normalizeDep($dep) { @@ -500,8 +500,10 @@ class ElggPluginManifest { break; } } - break; + default: + // unrecognized so we just return the raw dependency + return $dep; } $normalized_dep = $this->buildStruct($struct, $dep); diff --git a/engine/classes/ElggTranslit.php b/engine/classes/ElggTranslit.php new file mode 100644 index 000000000..676c59fc8 --- /dev/null +++ b/engine/classes/ElggTranslit.php @@ -0,0 +1,262 @@ +<?php +/** + * Elgg Transliterate + * + * For creating "friendly titles" for URLs + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information, see + * <http://www.doctrine-project.org>. + * + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Jonathan H. Wage <jonwage@gmail.com> + * + * @author Steve Clay <steve@mrclay.org> + * @package Elgg.Core + * + * @access private Plugin authors should not use this directly + */ +class ElggTranslit { + + /** + * Create a version of a string for embedding in a URL + * @param string $string a UTF-8 string + * @param string $separator + * @return string + */ + static public function urlize($string, $separator = '-') { + // Iñtërnâtiônàlizætiøn, AND 日本語! + + // try to force combined chars because the translit map and others expect it + if (self::hasNormalizerSupport()) { + $nfc = normalizer_normalize($string); + if (is_string($nfc)) { + $string = $nfc; + } + } + // Internationalization, AND 日本語! + $string = self::transliterateAscii($string); + + // more translation + $string = strtr($string, array( + // Euro/GBP + "\xE2\x82\xAC" /* € */ => 'E', "\xC2\xA3" /* £ */ => 'GBP', + )); + + // remove all ASCII except 0-9a-zA-Z, hyphen, underscore, and whitespace + // note: "x" modifier did not work with this pattern. + $string = preg_replace('~[' + . '\x00-\x08' # control chars + . '\x0b\x0c' # vert tab, form feed + . '\x0e-\x1f' # control chars + . '\x21-\x2c' # ! ... , + . '\x2e\x2f' # . slash + . '\x3a-\x40' # : ... @ + . '\x5b-\x5e' # [ ... ^ + . '\x60' # ` + . '\x7b-\x7f' # { ... DEL + . ']~', '', $string); + $string = strtr($string, '', ''); + + // internationalization, and 日本語! + // note: not using elgg_strtolower to keep this class portable + $string = is_callable('mb_strtolower') + ? mb_strtolower($string, 'UTF-8') + : strtolower($string); + + // split by ASCII chars not in 0-9a-zA-Z + // note: we cannot use [^0-9a-zA-Z] because that matches multibyte chars. + // note: "x" modifier did not work with this pattern. + $pattern = '~[' + . '\x00-\x2f' # controls ... slash + . '\x3a-\x40' # : ... @ + . '\x5b-\x60' # [ ... ` + . '\x7b-\x7f' # { ... DEL + . ']+~x'; + + // ['internationalization', 'and', '日本語'] + $words = preg_split($pattern, $string, -1, PREG_SPLIT_NO_EMPTY); + + // ['internationalization', 'and', '%E6%97%A5%E6%9C%AC%E8%AA%9E'] + $words = array_map('urlencode', $words); + + // internationalization-and-%E6%97%A5%E6%9C%AC%E8%AA%9E + return implode($separator, $words); + } + + /** + * Transliterate Western multibyte chars to ASCII + * @param string $utf8 a UTF-8 string + * @return string + */ + static public function transliterateAscii($utf8) { + static $map = null; + if (!preg_match('/[\x80-\xff]/', $utf8)) { + return $utf8; + } + if (null === $map) { + $map = self::getAsciiTranslitMap(); + } + return strtr($utf8, $map); + } + + /** + * Get array of UTF-8 (NFC) character replacements. + * + * @return array + */ + static public function getAsciiTranslitMap() { + return array( + // Decompositions for Latin-1 Supplement + "\xC2\xAA" /* ª */ => 'a', "\xC2\xBA" /* º */ => 'o', "\xC3\x80" /* À */ => 'A', + "\xC3\x81" /* Á */ => 'A', "\xC3\x82" /*  */ => 'A', "\xC3\x83" /* à */ => 'A', + "\xC3\x84" /* Ä */ => 'A', "\xC3\x85" /* Å */ => 'A', "\xC3\x86" /* Æ */ => 'AE', + "\xC3\x87" /* Ç */ => 'C', "\xC3\x88" /* È */ => 'E', "\xC3\x89" /* É */ => 'E', + "\xC3\x8A" /* Ê */ => 'E', "\xC3\x8B" /* Ë */ => 'E', "\xC3\x8C" /* Ì */ => 'I', + "\xC3\x8D" /* Í */ => 'I', "\xC3\x8E" /* Î */ => 'I', "\xC3\x8F" /* Ï */ => 'I', + "\xC3\x90" /* Ð */ => 'D', "\xC3\x91" /* Ñ */ => 'N', "\xC3\x92" /* Ò */ => 'O', + "\xC3\x93" /* Ó */ => 'O', "\xC3\x94" /* Ô */ => 'O', "\xC3\x95" /* Õ */ => 'O', + "\xC3\x96" /* Ö */ => 'O', "\xC3\x99" /* Ù */ => 'U', "\xC3\x9A" /* Ú */ => 'U', + "\xC3\x9B" /* Û */ => 'U', "\xC3\x9C" /* Ü */ => 'U', "\xC3\x9D" /* Ý */ => 'Y', + "\xC3\x9E" /* Þ */ => 'TH', "\xC3\x9F" /* ß */ => 'ss', "\xC3\xA0" /* à */ => 'a', + "\xC3\xA1" /* á */ => 'a', "\xC3\xA2" /* â */ => 'a', "\xC3\xA3" /* ã */ => 'a', + "\xC3\xA4" /* ä */ => 'a', "\xC3\xA5" /* å */ => 'a', "\xC3\xA6" /* æ */ => 'ae', + "\xC3\xA7" /* ç */ => 'c', "\xC3\xA8" /* è */ => 'e', "\xC3\xA9" /* é */ => 'e', + "\xC3\xAA" /* ê */ => 'e', "\xC3\xAB" /* ë */ => 'e', "\xC3\xAC" /* ì */ => 'i', + "\xC3\xAD" /* í */ => 'i', "\xC3\xAE" /* î */ => 'i', "\xC3\xAF" /* ï */ => 'i', + "\xC3\xB0" /* ð */ => 'd', "\xC3\xB1" /* ñ */ => 'n', "\xC3\xB2" /* ò */ => 'o', + "\xC3\xB3" /* ó */ => 'o', "\xC3\xB4" /* ô */ => 'o', "\xC3\xB5" /* õ */ => 'o', + "\xC3\xB6" /* ö */ => 'o', "\xC3\xB8" /* ø */ => 'o', "\xC3\xB9" /* ù */ => 'u', + "\xC3\xBA" /* ú */ => 'u', "\xC3\xBB" /* û */ => 'u', "\xC3\xBC" /* ü */ => 'u', + "\xC3\xBD" /* ý */ => 'y', "\xC3\xBE" /* þ */ => 'th', "\xC3\xBF" /* ÿ */ => 'y', + "\xC3\x98" /* Ø */ => 'O', + // Decompositions for Latin Extended-A + "\xC4\x80" /* Ā */ => 'A', "\xC4\x81" /* ā */ => 'a', "\xC4\x82" /* Ă */ => 'A', + "\xC4\x83" /* ă */ => 'a', "\xC4\x84" /* Ą */ => 'A', "\xC4\x85" /* ą */ => 'a', + "\xC4\x86" /* Ć */ => 'C', "\xC4\x87" /* ć */ => 'c', "\xC4\x88" /* Ĉ */ => 'C', + "\xC4\x89" /* ĉ */ => 'c', "\xC4\x8A" /* Ċ */ => 'C', "\xC4\x8B" /* ċ */ => 'c', + "\xC4\x8C" /* Č */ => 'C', "\xC4\x8D" /* č */ => 'c', "\xC4\x8E" /* Ď */ => 'D', + "\xC4\x8F" /* ď */ => 'd', "\xC4\x90" /* Đ */ => 'D', "\xC4\x91" /* đ */ => 'd', + "\xC4\x92" /* Ē */ => 'E', "\xC4\x93" /* ē */ => 'e', "\xC4\x94" /* Ĕ */ => 'E', + "\xC4\x95" /* ĕ */ => 'e', "\xC4\x96" /* Ė */ => 'E', "\xC4\x97" /* ė */ => 'e', + "\xC4\x98" /* Ę */ => 'E', "\xC4\x99" /* ę */ => 'e', "\xC4\x9A" /* Ě */ => 'E', + "\xC4\x9B" /* ě */ => 'e', "\xC4\x9C" /* Ĝ */ => 'G', "\xC4\x9D" /* ĝ */ => 'g', + "\xC4\x9E" /* Ğ */ => 'G', "\xC4\x9F" /* ğ */ => 'g', "\xC4\xA0" /* Ġ */ => 'G', + "\xC4\xA1" /* ġ */ => 'g', "\xC4\xA2" /* Ģ */ => 'G', "\xC4\xA3" /* ģ */ => 'g', + "\xC4\xA4" /* Ĥ */ => 'H', "\xC4\xA5" /* ĥ */ => 'h', "\xC4\xA6" /* Ħ */ => 'H', + "\xC4\xA7" /* ħ */ => 'h', "\xC4\xA8" /* Ĩ */ => 'I', "\xC4\xA9" /* ĩ */ => 'i', + "\xC4\xAA" /* Ī */ => 'I', "\xC4\xAB" /* ī */ => 'i', "\xC4\xAC" /* Ĭ */ => 'I', + "\xC4\xAD" /* ĭ */ => 'i', "\xC4\xAE" /* Į */ => 'I', "\xC4\xAF" /* į */ => 'i', + "\xC4\xB0" /* İ */ => 'I', "\xC4\xB1" /* ı */ => 'i', "\xC4\xB2" /* IJ */ => 'IJ', + "\xC4\xB3" /* ij */ => 'ij', "\xC4\xB4" /* Ĵ */ => 'J', "\xC4\xB5" /* ĵ */ => 'j', + "\xC4\xB6" /* Ķ */ => 'K', "\xC4\xB7" /* ķ */ => 'k', "\xC4\xB8" /* ĸ */ => 'k', + "\xC4\xB9" /* Ĺ */ => 'L', "\xC4\xBA" /* ĺ */ => 'l', "\xC4\xBB" /* Ļ */ => 'L', + "\xC4\xBC" /* ļ */ => 'l', "\xC4\xBD" /* Ľ */ => 'L', "\xC4\xBE" /* ľ */ => 'l', + "\xC4\xBF" /* Ŀ */ => 'L', "\xC5\x80" /* ŀ */ => 'l', "\xC5\x81" /* Ł */ => 'L', + "\xC5\x82" /* ł */ => 'l', "\xC5\x83" /* Ń */ => 'N', "\xC5\x84" /* ń */ => 'n', + "\xC5\x85" /* Ņ */ => 'N', "\xC5\x86" /* ņ */ => 'n', "\xC5\x87" /* Ň */ => 'N', + "\xC5\x88" /* ň */ => 'n', "\xC5\x89" /* ʼn */ => 'N', "\xC5\x8A" /* Ŋ */ => 'n', + "\xC5\x8B" /* ŋ */ => 'N', "\xC5\x8C" /* Ō */ => 'O', "\xC5\x8D" /* ō */ => 'o', + "\xC5\x8E" /* Ŏ */ => 'O', "\xC5\x8F" /* ŏ */ => 'o', "\xC5\x90" /* Ő */ => 'O', + "\xC5\x91" /* ő */ => 'o', "\xC5\x92" /* Œ */ => 'OE', "\xC5\x93" /* œ */ => 'oe', + "\xC5\x94" /* Ŕ */ => 'R', "\xC5\x95" /* ŕ */ => 'r', "\xC5\x96" /* Ŗ */ => 'R', + "\xC5\x97" /* ŗ */ => 'r', "\xC5\x98" /* Ř */ => 'R', "\xC5\x99" /* ř */ => 'r', + "\xC5\x9A" /* Ś */ => 'S', "\xC5\x9B" /* ś */ => 's', "\xC5\x9C" /* Ŝ */ => 'S', + "\xC5\x9D" /* ŝ */ => 's', "\xC5\x9E" /* Ş */ => 'S', "\xC5\x9F" /* ş */ => 's', + "\xC5\xA0" /* Š */ => 'S', "\xC5\xA1" /* š */ => 's', "\xC5\xA2" /* Ţ */ => 'T', + "\xC5\xA3" /* ţ */ => 't', "\xC5\xA4" /* Ť */ => 'T', "\xC5\xA5" /* ť */ => 't', + "\xC5\xA6" /* Ŧ */ => 'T', "\xC5\xA7" /* ŧ */ => 't', "\xC5\xA8" /* Ũ */ => 'U', + "\xC5\xA9" /* ũ */ => 'u', "\xC5\xAA" /* Ū */ => 'U', "\xC5\xAB" /* ū */ => 'u', + "\xC5\xAC" /* Ŭ */ => 'U', "\xC5\xAD" /* ŭ */ => 'u', "\xC5\xAE" /* Ů */ => 'U', + "\xC5\xAF" /* ů */ => 'u', "\xC5\xB0" /* Ű */ => 'U', "\xC5\xB1" /* ű */ => 'u', + "\xC5\xB2" /* Ų */ => 'U', "\xC5\xB3" /* ų */ => 'u', "\xC5\xB4" /* Ŵ */ => 'W', + "\xC5\xB5" /* ŵ */ => 'w', "\xC5\xB6" /* Ŷ */ => 'Y', "\xC5\xB7" /* ŷ */ => 'y', + "\xC5\xB8" /* Ÿ */ => 'Y', "\xC5\xB9" /* Ź */ => 'Z', "\xC5\xBA" /* ź */ => 'z', + "\xC5\xBB" /* Ż */ => 'Z', "\xC5\xBC" /* ż */ => 'z', "\xC5\xBD" /* Ž */ => 'Z', + "\xC5\xBE" /* ž */ => 'z', "\xC5\xBF" /* ſ */ => 's', + // Decompositions for Latin Extended-B + "\xC8\x98" /* Ș */ => 'S', "\xC8\x99" /* ș */ => 's', + "\xC8\x9A" /* Ț */ => 'T', "\xC8\x9B" /* ț */ => 't', + // unmarked + "\xC6\xA0" /* Ơ */ => 'O', "\xC6\xA1" /* ơ */ => 'o', + "\xC6\xAF" /* Ư */ => 'U', "\xC6\xB0" /* ư */ => 'u', + // grave accent + "\xE1\xBA\xA6" /* Ầ */ => 'A', "\xE1\xBA\xA7" /* ầ */ => 'a', + "\xE1\xBA\xB0" /* Ằ */ => 'A', "\xE1\xBA\xB1" /* ằ */ => 'a', + "\xE1\xBB\x80" /* Ề */ => 'E', "\xE1\xBB\x81" /* ề */ => 'e', + "\xE1\xBB\x92" /* Ồ */ => 'O', "\xE1\xBB\x93" /* ồ */ => 'o', + "\xE1\xBB\x9C" /* Ờ */ => 'O', "\xE1\xBB\x9D" /* ờ */ => 'o', + "\xE1\xBB\xAA" /* Ừ */ => 'U', "\xE1\xBB\xAB" /* ừ */ => 'u', + "\xE1\xBB\xB2" /* Ỳ */ => 'Y', "\xE1\xBB\xB3" /* ỳ */ => 'y', + // hook + "\xE1\xBA\xA2" /* Ả */ => 'A', "\xE1\xBA\xA3" /* ả */ => 'a', + "\xE1\xBA\xA8" /* Ẩ */ => 'A', "\xE1\xBA\xA9" /* ẩ */ => 'a', + "\xE1\xBA\xB2" /* Ẳ */ => 'A', "\xE1\xBA\xB3" /* ẳ */ => 'a', + "\xE1\xBA\xBA" /* Ẻ */ => 'E', "\xE1\xBA\xBB" /* ẻ */ => 'e', + "\xE1\xBB\x82" /* Ể */ => 'E', "\xE1\xBB\x83" /* ể */ => 'e', + "\xE1\xBB\x88" /* Ỉ */ => 'I', "\xE1\xBB\x89" /* ỉ */ => 'i', + "\xE1\xBB\x8E" /* Ỏ */ => 'O', "\xE1\xBB\x8F" /* ỏ */ => 'o', + "\xE1\xBB\x94" /* Ổ */ => 'O', "\xE1\xBB\x95" /* ổ */ => 'o', + "\xE1\xBB\x9E" /* Ở */ => 'O', "\xE1\xBB\x9F" /* ở */ => 'o', + "\xE1\xBB\xA6" /* Ủ */ => 'U', "\xE1\xBB\xA7" /* ủ */ => 'u', + "\xE1\xBB\xAC" /* Ử */ => 'U', "\xE1\xBB\xAD" /* ử */ => 'u', + "\xE1\xBB\xB6" /* Ỷ */ => 'Y', "\xE1\xBB\xB7" /* ỷ */ => 'y', + // tilde + "\xE1\xBA\xAA" /* Ẫ */ => 'A', "\xE1\xBA\xAB" /* ẫ */ => 'a', + "\xE1\xBA\xB4" /* Ẵ */ => 'A', "\xE1\xBA\xB5" /* ẵ */ => 'a', + "\xE1\xBA\xBC" /* Ẽ */ => 'E', "\xE1\xBA\xBD" /* ẽ */ => 'e', + "\xE1\xBB\x84" /* Ễ */ => 'E', "\xE1\xBB\x85" /* ễ */ => 'e', + "\xE1\xBB\x96" /* Ỗ */ => 'O', "\xE1\xBB\x97" /* ỗ */ => 'o', + "\xE1\xBB\xA0" /* Ỡ */ => 'O', "\xE1\xBB\xA1" /* ỡ */ => 'o', + "\xE1\xBB\xAE" /* Ữ */ => 'U', "\xE1\xBB\xAF" /* ữ */ => 'u', + "\xE1\xBB\xB8" /* Ỹ */ => 'Y', "\xE1\xBB\xB9" /* ỹ */ => 'y', + // acute accent + "\xE1\xBA\xA4" /* Ấ */ => 'A', "\xE1\xBA\xA5" /* ấ */ => 'a', + "\xE1\xBA\xAE" /* Ắ */ => 'A', "\xE1\xBA\xAF" /* ắ */ => 'a', + "\xE1\xBA\xBE" /* Ế */ => 'E', "\xE1\xBA\xBF" /* ế */ => 'e', + "\xE1\xBB\x90" /* Ố */ => 'O', "\xE1\xBB\x91" /* ố */ => 'o', + "\xE1\xBB\x9A" /* Ớ */ => 'O', "\xE1\xBB\x9B" /* ớ */ => 'o', + "\xE1\xBB\xA8" /* Ứ */ => 'U', "\xE1\xBB\xA9" /* ứ */ => 'u', + // dot below + "\xE1\xBA\xA0" /* Ạ */ => 'A', "\xE1\xBA\xA1" /* ạ */ => 'a', + "\xE1\xBA\xAC" /* Ậ */ => 'A', "\xE1\xBA\xAD" /* ậ */ => 'a', + "\xE1\xBA\xB6" /* Ặ */ => 'A', "\xE1\xBA\xB7" /* ặ */ => 'a', + "\xE1\xBA\xB8" /* Ẹ */ => 'E', "\xE1\xBA\xB9" /* ẹ */ => 'e', + "\xE1\xBB\x86" /* Ệ */ => 'E', "\xE1\xBB\x87" /* ệ */ => 'e', + "\xE1\xBB\x8A" /* Ị */ => 'I', "\xE1\xBB\x8B" /* ị */ => 'i', + "\xE1\xBB\x8C" /* Ọ */ => 'O', "\xE1\xBB\x8D" /* ọ */ => 'o', + "\xE1\xBB\x98" /* Ộ */ => 'O', "\xE1\xBB\x99" /* ộ */ => 'o', + "\xE1\xBB\xA2" /* Ợ */ => 'O', "\xE1\xBB\xA3" /* ợ */ => 'o', + "\xE1\xBB\xA4" /* Ụ */ => 'U', "\xE1\xBB\xA5" /* ụ */ => 'u', + "\xE1\xBB\xB0" /* Ự */ => 'U', "\xE1\xBB\xB1" /* ự */ => 'u', + "\xE1\xBB\xB4" /* Ỵ */ => 'Y', "\xE1\xBB\xB5" /* ỵ */ => 'y', + ); + } + + /** + * Tests that "normalizer_normalize" exists and works + * @return bool + */ + static public function hasNormalizerSupport() { + static $ret = null; + if (null === $ret) { + $form_c = "\xC3\x85"; // 'LATIN CAPITAL LETTER A WITH RING ABOVE' (U+00C5) + $form_d = "A\xCC\x8A"; // A followed by 'COMBINING RING ABOVE' (U+030A) + $ret = (function_exists('normalizer_normalize') + && $form_c === normalizer_normalize($form_d)); + } + return $ret; + } +} diff --git a/engine/lib/actions.php b/engine/lib/actions.php index 3a7c02488..53b185dea 100644 --- a/engine/lib/actions.php +++ b/engine/lib/actions.php @@ -82,44 +82,28 @@ function action($action, $forwarder = "") { $forwarder = str_replace(elgg_get_site_url(), "", $forwarder); $forwarder = str_replace("http://", "", $forwarder); $forwarder = str_replace("@", "", $forwarder); - if (substr($forwarder, 0, 1) == "/") { $forwarder = substr($forwarder, 1); } - if (isset($CONFIG->actions[$action])) { - if (elgg_is_admin_logged_in() || ($CONFIG->actions[$action]['access'] !== 'admin')) { - if (elgg_is_logged_in() || ($CONFIG->actions[$action]['access'] === 'public')) { - - // Trigger action event - // @todo This is only called before the primary action is called. - $event_result = true; - $event_result = elgg_trigger_plugin_hook('action', $action, null, $event_result); - - // Include action - // Event_result being false doesn't produce an error - // since i assume this will be handled in the hook itself. - // @todo make this better! - if ($event_result) { - if (!include($CONFIG->actions[$action]['file'])) { - register_error(elgg_echo('actionnotfound', array($action))); - } - } - } else { - register_error(elgg_echo('actionloggedout')); + if (!isset($CONFIG->actions[$action])) { + register_error(elgg_echo('actionundefined', array($action))); + } elseif (!elgg_is_admin_logged_in() && ($CONFIG->actions[$action]['access'] === 'admin')) { + register_error(elgg_echo('actionunauthorized')); + } elseif (!elgg_is_logged_in() && ($CONFIG->actions[$action]['access'] !== 'public')) { + register_error(elgg_echo('actionloggedout')); + } else { + // Returning falsy doesn't produce an error + // We assume this will be handled in the hook itself. + if (elgg_trigger_plugin_hook('action', $action, null, true)) { + if (!include($CONFIG->actions[$action]['file'])) { + register_error(elgg_echo('actionnotfound', array($action))); } - } else { - register_error(elgg_echo('actionunauthorized')); } - } else { - register_error(elgg_echo('actionundefined', array($action))); } - if (!empty($forwarder)) { - forward($forwarder); - } else { - forward(REFERER); - } + $forwarder = empty($forwarder) ? REFERER : $forwarder; + forward($forwarder); } /** diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 0ff3a43dc..77fa30e41 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -361,13 +361,24 @@ function elgg_enable_metadata(array $options) { * options available to elgg_get_entities(). Supports * the singular option shortcut. * - * NB: Using metadata_names and metadata_values results in a + * @note Using metadata_names and metadata_values results in a * "names IN (...) AND values IN (...)" clause. This is subtly * differently than default multiple metadata_name_value_pairs, which use * "(name = value) AND (name = value)" clauses. * * When in doubt, use name_value_pairs. * + * To ask for entities that do not have a metadata value, use a custom + * where clause like this: + * + * $options['wheres'][] = "NOT EXISTS ( + * SELECT 1 FROM {$dbprefix}metadata md + * WHERE md.entity_guid = e.guid + * AND md.name_id = $name_metastring_id + * AND md.value_id = $value_metastring_id)"; + * + * Note the metadata name and value has been denormalized in the above example. + * * @see elgg_get_entities * * @param array $options Array in format: diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php index 4ff009bfb..10b11acfe 100644 --- a/engine/lib/navigation.php +++ b/engine/lib/navigation.php @@ -335,6 +335,19 @@ function elgg_river_menu_setup($hook, $type, $return, $params) { $return[] = ElggMenuItem::factory($options); } } + + if (elgg_is_admin_logged_in()) { + $options = array( + 'name' => 'delete', + 'href' => "action/river/delete?id=$item->id", + 'text' => elgg_view_icon('delete'), + 'title' => elgg_echo('delete'), + 'confirm' => elgg_echo('deleteconfirm'), + 'is_action' => true, + 'priority' => 200, + ); + $return[] = ElggMenuItem::factory($options); + } } return $return; diff --git a/engine/lib/output.php b/engine/lib/output.php index b1245a924..7bfc4be6e 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -310,19 +310,11 @@ function elgg_get_friendly_title($title) { return $result; } - // @todo not using this because of locale concerns - //$title = iconv('UTF-8', 'ASCII//TRANSLIT', $title); - - // @todo this uses a utf8 character class. can use if - // we want to support utf8 in the url. - //$title = preg_replace('/[^\p{L}\- ]/u', '', $title); - - // use A-Za-z0-9_ instead of \w because \w is locale sensitive - $title = preg_replace("/[^A-Za-z0-9_\- ]/", "", $title); - $title = str_replace(" ", "-", $title); - $title = str_replace("--", "-", $title); - $title = trim($title); - $title = elgg_strtolower($title); + // handle some special cases + $title = str_replace('&', 'and', $title); + + $title = ElggTranslit::urlize($title); + return $title; } diff --git a/engine/lib/pagehandler.php b/engine/lib/pagehandler.php index 46c7d059e..ba7518a77 100644 --- a/engine/lib/pagehandler.php +++ b/engine/lib/pagehandler.php @@ -31,18 +31,18 @@ function page_handler($handler, $page) { } // return false to stop processing the request (because you handled it) - // return a new $params array if you want to route the request differently - $params = array( + // return a new $request array if you want to route the request differently + $request = array( 'handler' => $handler, 'segments' => $page, ); - $params = elgg_trigger_plugin_hook('route', $handler, NULL, $params); - if ($params === false) { + $request = elgg_trigger_plugin_hook('route', $handler, null, $request); + if ($request === false) { return true; } - $handler = $params['handler']; - $page = $params['segments']; + $handler = $request['handler']; + $page = $request['segments']; $result = false; if (isset($CONFIG->pagehandler) && !empty($handler) && isset($CONFIG->pagehandler[$handler])) { diff --git a/engine/lib/relationships.php b/engine/lib/relationships.php index f50c4a485..09d541e22 100644 --- a/engine/lib/relationships.php +++ b/engine/lib/relationships.php @@ -239,6 +239,15 @@ function get_entity_relationships($guid, $inverse_relationship = FALSE) { * Also accepts all options available to elgg_get_entities() and * elgg_get_entities_from_metadata(). * + * To ask for entities that do not have a particulat relationship to an entity, + * use a custom where clause like the following: + * + * $options['wheres'][] = "NOT EXISTS ( + * SELECT 1 FROM {$db_prefix}entity_relationships + * WHERE guid_one = e.guid + * AND relationship = '$relationship' + * )"; + * * @see elgg_get_entities * @see elgg_get_entities_from_metadata * diff --git a/engine/lib/river.php b/engine/lib/river.php index 711832f70..b717a7756 100644 --- a/engine/lib/river.php +++ b/engine/lib/river.php @@ -643,9 +643,11 @@ function elgg_river_init() { elgg_register_page_handler('activity', 'elgg_river_page_handler'); $item = new ElggMenuItem('activity', elgg_echo('activity'), 'activity'); elgg_register_menu_item('site', $item); - + elgg_register_widget_type('river_widget', elgg_echo('river:widget:title'), elgg_echo('river:widget:description')); + elgg_register_action('river/delete', '', 'admin'); + elgg_register_plugin_hook_handler('unit_test', 'system', 'elgg_river_test'); } diff --git a/engine/lib/users.php b/engine/lib/users.php index 241b524f9..527eff3cd 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -136,7 +136,6 @@ function ban_user($user_guid, $reason = "") { global $CONFIG; $user_guid = (int)$user_guid; - $reason = sanitise_string($reason); $user = get_entity($user_guid); diff --git a/engine/lib/views.php b/engine/lib/views.php index 25acbf2b2..b00334062 100644 --- a/engine/lib/views.php +++ b/engine/lib/views.php @@ -303,7 +303,7 @@ function elgg_set_view_location($view, $location, $viewtype = '') { /** * Returns whether the specified view exists * - * @note If $recurse is strue, also checks if a view exists only as an extension. + * @note If $recurse is true, also checks if a view exists only as an extension. * * @param string $view The view name * @param string $viewtype If set, forces the viewtype diff --git a/engine/tests/api/metadata.php b/engine/tests/api/metadata.php index 244036f80..9933263d1 100644 --- a/engine/tests/api/metadata.php +++ b/engine/tests/api/metadata.php @@ -28,6 +28,9 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest { public function testGetMetastringById() { foreach (array('metaUnitTest', 'metaunittest', 'METAUNITTEST') as $string) { + // since there is no guarantee that metastrings are garbage collected + // between unit test runs, we delete before testing + $this->delete_metastrings($string); $this->create_metastring($string); } @@ -194,11 +197,19 @@ class ElggCoreMetadataAPITest extends ElggCoreUnitTest { $u2->delete(); } + protected function delete_metastrings($string) { + global $CONFIG, $METASTRINGS_CACHE, $METASTRINGS_DEADNAME_CACHE; + $METASTRINGS_CACHE = $METASTRINGS_DEADNAME_CACHE = array(); + + $string = sanitise_string($string); + mysql_query("DELETE FROM {$CONFIG->dbprefix}metastrings WHERE string = BINARY '$string'"); + } protected function create_metastring($string) { global $CONFIG, $METASTRINGS_CACHE, $METASTRINGS_DEADNAME_CACHE; $METASTRINGS_CACHE = $METASTRINGS_DEADNAME_CACHE = array(); + $string = sanitise_string($string); mysql_query("INSERT INTO {$CONFIG->dbprefix}metastrings (string) VALUES ('$string')"); $this->metastrings[$string] = mysql_insert_id(); } diff --git a/engine/tests/regression/trac_bugs.php b/engine/tests/regression/trac_bugs.php index 26a45ab6a..691433a41 100644 --- a/engine/tests/regression/trac_bugs.php +++ b/engine/tests/regression/trac_bugs.php @@ -202,16 +202,33 @@ class ElggCoreRegressionBugsTest extends ElggCoreUnitTest { /** * http://trac.elgg.org/ticket/3210 - Don't remove -s in friendly titles - * @todo: http://trac.elgg.org/ticket/2276 - improve char encoding + * http://trac.elgg.org/ticket/2276 - improve char encoding */ public function test_friendly_title() { $cases = array( - 'Simple Test' => 'simple-test', - 'Test top-level page' => 'test-top-level-page', -// 'éclair' => 'éclair', -// 'English, Español, and 日本語' => 'english-español-and-日本語' + // 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-a-a-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + + // separators trimmed + "-_ 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 + if (ElggTranslit::hasNormalizerSupport()) { + $form_d = "A\xCC\x8A"; // A followed by 'COMBINING RING ABOVE' (U+030A) + $cases[$form_d] = "a"; + } + foreach ($cases as $case => $expected) { $friendly_title = elgg_get_friendly_title($case); $this->assertIdentical($expected, $friendly_title); diff --git a/languages/en.php b/languages/en.php index 7cd091115..01b4d5d6b 100644 --- a/languages/en.php +++ b/languages/en.php @@ -437,6 +437,8 @@ $english = array( 'river:ingroup' => 'in the group %s', 'river:none' => 'No activity', 'river:update' => 'Update for %s', + 'river:delete:success' => 'River item has been deleted', + 'river:delete:fail' => 'River item could not be deleted', 'river:widget:title' => "Activity", 'river:widget:description' => "Display latest activity", @@ -875,6 +877,7 @@ $english = array( 'down' => 'Down', 'top' => 'Top', 'bottom' => 'Bottom', + 'back' => 'Back', 'invite' => "Invite", diff --git a/mod/blog/lib/blog.php b/mod/blog/lib/blog.php index 9a02a8cc3..4622a9e7e 100644 --- a/mod/blog/lib/blog.php +++ b/mod/blog/lib/blog.php @@ -272,7 +272,6 @@ function blog_get_page_content_edit($page, $guid = 0, $revision = NULL) { $vars = array(); $vars['id'] = 'blog-post-edit'; - $vars['name'] = 'blog_post'; $vars['class'] = 'elgg-form-alt'; if ($page == 'edit') { diff --git a/mod/blog/views/default/js/blog/save_draft.php b/mod/blog/views/default/js/blog/save_draft.php index 8a994ffb0..8cd07ff5d 100644 --- a/mod/blog/views/default/js/blog/save_draft.php +++ b/mod/blog/views/default/js/blog/save_draft.php @@ -12,7 +12,7 @@ elgg.provide('elgg.blog'); */ elgg.blog.saveDraftCallback = function(data, textStatus, XHR) { if (textStatus == 'success' && data.success == true) { - var form = $('form[name=blog_post]'); + var form = $('form[id=blog-post-edit]'); // update the guid input element for new posts that now have a guid form.find('input[name=guid]').val(data.guid); @@ -36,7 +36,7 @@ elgg.blog.saveDraft = function() { } // only save on changed content - var form = $('form[name=blog_post]'); + var form = $('form[id=blog-post-edit]'); var description = form.find('textarea[name=description]').val(); var title = form.find('input[name=title]').val(); @@ -59,7 +59,7 @@ elgg.blog.saveDraft = function() { elgg.blog.init = function() { // get a copy of the body to compare for auto save - oldDescription = $('form[name=blog_post]').find('textarea[name=description]').val(); + oldDescription = $('form[id=blog-post-edit]').find('textarea[name=description]').val(); setInterval(elgg.blog.saveDraft, 60000); }; diff --git a/mod/bookmarks/start.php b/mod/bookmarks/start.php index 56bac984a..66e22b565 100644 --- a/mod/bookmarks/start.php +++ b/mod/bookmarks/start.php @@ -86,8 +86,13 @@ function bookmarks_init() { * @return bool */ function bookmarks_page_handler($page) { + elgg_load_library('elgg:bookmarks'); + if (!isset($page[0])) { + $page[0] = 'all'; + } + elgg_push_breadcrumb(elgg_echo('bookmarks'), 'bookmarks/all'); // old group usernames diff --git a/mod/externalpages/views/default/expages/wrapper.php b/mod/externalpages/views/default/expages/wrapper.php index 8eb0b2f84..c579da1ba 100644 --- a/mod/externalpages/views/default/expages/wrapper.php +++ b/mod/externalpages/views/default/expages/wrapper.php @@ -9,7 +9,7 @@ echo $vars['content']; echo '<div class="mtm">'; echo elgg_view('output/url', array( - 'text' => 'Back', + 'text' => elgg_echo('back'), 'href' => $_SERVER['HTTP_REFERER'], 'class' => 'float-alt' )); diff --git a/mod/groups/actions/groups/edit.php b/mod/groups/actions/groups/edit.php index b513a6098..a3ad91622 100644 --- a/mod/groups/actions/groups/edit.php +++ b/mod/groups/actions/groups/edit.php @@ -15,6 +15,8 @@ function profile_array_decoder(&$v) { $v = html_entity_decode($v, ENT_COMPAT, 'UTF-8'); } +elgg_make_sticky_form('groups'); + // Get group fields $input = array(); foreach ($CONFIG->group as $shortname => $valuetype) { @@ -106,6 +108,9 @@ if (elgg_get_plugin_setting('hidden_groups', 'groups') == 'yes') { $group->save(); +// group saved so clear sticky form +elgg_clear_sticky_form('groups'); + // group creator needs to be member of new group and river entry created if ($new_group_flag) { elgg_set_page_owner_guid($group->guid); diff --git a/mod/groups/languages/en.php b/mod/groups/languages/en.php index 88aeccb54..4868aa334 100644 --- a/mod/groups/languages/en.php +++ b/mod/groups/languages/en.php @@ -12,6 +12,7 @@ $english = array( */ 'groups' => "Groups", 'groups:owned' => "Groups I own", + 'groups:owned:user' => 'Groups %s owns', 'groups:yours' => "My groups", 'groups:user' => "%s's groups", 'groups:all' => "All groups", diff --git a/mod/groups/lib/discussion.php b/mod/groups/lib/discussion.php index 02ab27fdc..ab2fe4849 100644 --- a/mod/groups/lib/discussion.php +++ b/mod/groups/lib/discussion.php @@ -15,7 +15,7 @@ function discussion_handle_all_page() { 'type' => 'object', 'subtype' => 'groupforumtopic', 'order_by' => 'e.last_action desc', - 'limit' => 40, + 'limit' => 20, 'full_view' => false, )); diff --git a/mod/groups/lib/groups.php b/mod/groups/lib/groups.php index 498766df0..51ae89a87 100644 --- a/mod/groups/lib/groups.php +++ b/mod/groups/lib/groups.php @@ -106,7 +106,11 @@ function groups_handle_owned_page() { $page_owner = elgg_get_page_owner_entity(); - $title = elgg_echo('groups:owned'); + if ($page_owner->guid == elgg_get_logged_in_user_guid()) { + $title = elgg_echo('groups:owned'); + } else { + $title = elgg_echo('groups:owned:user', array($page_owner->name)); + } elgg_push_breadcrumb($title); elgg_register_title_button(); @@ -137,7 +141,11 @@ function groups_handle_mine_page() { $page_owner = elgg_get_page_owner_entity(); - $title = elgg_echo('groups:yours'); + if ($page_owner->guid == elgg_get_logged_in_user_guid()) { + $title = elgg_echo('groups:yours'); + } else { + $title = elgg_echo('groups:user', array($page_owner->name)); + } elgg_push_breadcrumb($title); elgg_register_title_button(); @@ -238,6 +246,8 @@ function groups_handle_profile_page($guid) { global $autofeed; $autofeed = true; + elgg_push_context('group_profile'); + $group = get_entity($guid); if (!$group) { forward('groups/all'); diff --git a/mod/groups/start.php b/mod/groups/start.php index 193b72a4e..c591410c5 100644 --- a/mod/groups/start.php +++ b/mod/groups/start.php @@ -141,35 +141,34 @@ function groups_setup_sidebar_menus() { // Get the page owner entity $page_owner = elgg_get_page_owner_entity(); - if (elgg_get_context() == 'groups') { - if ($page_owner instanceof ElggGroup) { - if (elgg_is_logged_in() && $page_owner->canEdit() && !$page_owner->isPublicMembership()) { - $url = elgg_get_site_url() . "groups/requests/{$page_owner->getGUID()}"; - elgg_register_menu_item('page', array( - 'name' => 'membership_requests', - 'text' => elgg_echo('groups:membershiprequests'), - 'href' => $url, - )); - } - } else { + if (elgg_in_context('group_profile')) { + if (elgg_is_logged_in() && $page_owner->canEdit() && !$page_owner->isPublicMembership()) { + $url = elgg_get_site_url() . "groups/requests/{$page_owner->getGUID()}"; elgg_register_menu_item('page', array( - 'name' => 'groups:all', - 'text' => elgg_echo('groups:all'), - 'href' => 'groups/all', + 'name' => 'membership_requests', + 'text' => elgg_echo('groups:membershiprequests'), + 'href' => $url, )); + } + } + if (elgg_get_context() == 'groups' && !elgg_instanceof($page_owner, 'group')) { + elgg_register_menu_item('page', array( + 'name' => 'groups:all', + 'text' => elgg_echo('groups:all'), + 'href' => 'groups/all', + )); - $user = elgg_get_logged_in_user_entity(); - if ($user) { - $url = "groups/owner/$user->username"; - $item = new ElggMenuItem('groups:owned', elgg_echo('groups:owned'), $url); - elgg_register_menu_item('page', $item); - $url = "groups/member/$user->username"; - $item = new ElggMenuItem('groups:member', elgg_echo('groups:yours'), $url); - elgg_register_menu_item('page', $item); - $url = "groups/invitations/$user->username"; - $item = new ElggMenuItem('groups:user:invites', elgg_echo('groups:invitations'), $url); - elgg_register_menu_item('page', $item); - } + $user = elgg_get_logged_in_user_entity(); + if ($user) { + $url = "groups/owner/$user->username"; + $item = new ElggMenuItem('groups:owned', elgg_echo('groups:owned'), $url); + elgg_register_menu_item('page', $item); + $url = "groups/member/$user->username"; + $item = new ElggMenuItem('groups:member', elgg_echo('groups:yours'), $url); + elgg_register_menu_item('page', $item); + $url = "groups/invitations/$user->username"; + $item = new ElggMenuItem('groups:user:invites', elgg_echo('groups:invitations'), $url); + elgg_register_menu_item('page', $item); } } } @@ -197,6 +196,10 @@ function groups_page_handler($page) { elgg_load_library('elgg:groups'); + if (!isset($page[0])) { + $page[0] = 'all'; + } + elgg_push_breadcrumb(elgg_echo('groups'), "groups/all"); switch ($page[0]) { @@ -786,6 +789,10 @@ function discussion_page_handler($page) { elgg_load_library('elgg:discussion'); + if (!isset($page[0])) { + $page[0] = 'all'; + } + elgg_push_breadcrumb(elgg_echo('discussion'), 'discussion/all'); switch ($page[0]) { diff --git a/mod/groups/views/default/forms/groups/edit.php b/mod/groups/views/default/forms/groups/edit.php index 8055b6430..7540d1bf9 100644 --- a/mod/groups/views/default/forms/groups/edit.php +++ b/mod/groups/views/default/forms/groups/edit.php @@ -5,8 +5,16 @@ * @package ElggGroups */ +if (elgg_is_sticky_form('groups')) { + $sticky_values = elgg_get_sticky_values('groups'); + elgg_clear_sticky_form('groups'); +} + // new groups default to open membership -if (isset($vars['entity'])) { +if (isset($sticky_values)) { + $membership = $sticky_values['membership']; + $access = $sticky_values['access_id']; +} elseif (isset($vars['entity'])) { $membership = $vars['entity']->membership; $access = $vars['entity']->access_id; if ($access != ACCESS_PUBLIC && $access != ACCESS_LOGGED_IN) { @@ -27,7 +35,7 @@ if (isset($vars['entity'])) { <label><?php echo elgg_echo("groups:name"); ?></label><br /> <?php echo elgg_view("input/text", array( 'name' => 'name', - 'value' => $vars['entity']->name, + 'value' => isset($sticky_values['name']) ? $sticky_values['name'] : $vars['entity']->name, )); ?> </div> @@ -45,7 +53,7 @@ if ($group_profile_fields > 0) { echo "</label>$line_break"; echo elgg_view("input/{$valtype}", array( 'name' => $shortname, - 'value' => $vars['entity']->$shortname, + 'value' => isset($sticky_values[$shortname]) ? $sticky_values[$shortname] : $vars['entity']->$shortname, )); echo '</div>'; } diff --git a/mod/htmlawed/start.php b/mod/htmlawed/start.php index 10bea2a52..12b6470a3 100644 --- a/mod/htmlawed/start.php +++ b/mod/htmlawed/start.php @@ -18,6 +18,8 @@ function htmlawed_init() { $lib = elgg_get_plugins_path() . "htmlawed/vendors/htmLawed/htmLawed.php"; elgg_register_library('htmlawed', $lib); + + elgg_register_plugin_hook_handler('unit_test', 'system', 'htmlawed_test'); } /** @@ -90,7 +92,13 @@ function htmLawedArray(&$v, $k, $htmlawed_config) { * @param array $attributes An array of attributes * @return string */ -function htmlawed_tag_post_processor($element, $attributes) { +function htmlawed_tag_post_processor($element, $attributes = false) { + if ($attributes === false) { + // This is a closing tag. Prevent further processing to avoid inserting a duplicate tag + + return "</${element}>"; + } + // these are the default styles used by tinymce. $allowed_styles = array( 'color', 'cursor', 'text-align', 'vertical-align', 'font-size', @@ -143,3 +151,15 @@ function htmlawed_tag_post_processor($element, $attributes) { $r = "<$element$string>"; return $r; } + +/** + * Runs unit tests for htmlawed + * + * @return array + * */ +function htmlawed_test($hook, $type, $value, $params) { + global $CONFIG; + + $value[] = dirname(__FILE__) . '/tests/tags.php'; + return $value; +} diff --git a/mod/htmlawed/tests/tags.php b/mod/htmlawed/tests/tags.php new file mode 100644 index 000000000..b3914a9d6 --- /dev/null +++ b/mod/htmlawed/tests/tags.php @@ -0,0 +1,45 @@ +<?php +/** + * Dupplicated tags in htmlawed + */ +class HtmLawedDuplicateTagsTest extends ElggCoreUnitTest { + + /** + * Called before each test object. + */ + public function __construct() { + parent::__construct(); + } + + /** + * Called before each test method. + */ + public function setUp() { + } + + /** + * Called after each test method. + */ + public function tearDown() { + // do not allow SimpleTest to interpret Elgg notices as exceptions + $this->swallowErrors(); + } + + /** + * Called after each test object. + */ + public function __destruct() { + elgg_set_ignore_access($this->ia); + // all __destruct() code should go above here + parent::__destruct(); + } + + public function testNotDuplicateTags() { + $filter_html = '<ul><li>item</li></ul>'; + set_input('test', $filter_html); + + $expected = $filter_html; + $result = get_input('test'); + $this->assertEqual($result, $expected); + } +}
\ No newline at end of file diff --git a/mod/pages/lib/pages.php b/mod/pages/lib/pages.php index 3f27118a6..9a9ba12e9 100644 --- a/mod/pages/lib/pages.php +++ b/mod/pages/lib/pages.php @@ -103,16 +103,18 @@ function pages_register_navigation_tree($container) { 'metadata_value' => $parent->getGUID(), 'limit' => 0, )); - - foreach ($children as $child) { - elgg_register_menu_item('pages_nav', array( - 'name' => $child->getGUID(), - 'text' => $child->title, - 'href' => $child->getURL(), - 'parent_name' => $parent->getGUID(), - )); - array_push($stack, $child); + + if ($children) { + foreach ($children as $child) { + elgg_register_menu_item('pages_nav', array( + 'name' => $child->getGUID(), + 'text' => $child->title, + 'href' => $child->getURL(), + 'parent_name' => $parent->getGUID(), + )); + array_push($stack, $child); + } } } } -}
\ No newline at end of file +} diff --git a/mod/pages/start.php b/mod/pages/start.php index c385131bd..6b0ad38b0 100644 --- a/mod/pages/start.php +++ b/mod/pages/start.php @@ -30,7 +30,6 @@ function pages_init() { // Register some actions $action_base = elgg_get_plugins_path() . 'pages/actions/pages'; elgg_register_action("pages/edit", "$action_base/edit.php"); - elgg_register_action("pages/editwelcome", "$action_base/editwelcome.php"); elgg_register_action("pages/delete", "$action_base/delete.php"); // Extend the main css view diff --git a/mod/profile/icondirect.php b/mod/profile/icondirect.php index 6c3148f2b..c4439f78c 100644 --- a/mod/profile/icondirect.php +++ b/mod/profile/icondirect.php @@ -11,6 +11,12 @@ require_once(dirname(dirname(dirname(__FILE__))). '/engine/settings.php'); global $CONFIG; +// won't be able to serve anything if no joindate or guid +if (!isset($_GET['joindate']) || !isset($_GET['guid'])) { + header("HTTP/1.1 404 Not Found"); + exit; +} + $join_date = (int)$_GET['joindate']; $last_cache = (int)$_GET['lastcache']; // icontime $guid = (int)$_GET['guid']; diff --git a/mod/profile/start.php b/mod/profile/start.php index abe044632..ab596f235 100644 --- a/mod/profile/start.php +++ b/mod/profile/start.php @@ -56,6 +56,8 @@ function profile_page_handler($page) { $username = $page[0]; $user = get_user_by_username($username); elgg_set_page_owner_guid($user->guid); + } elseif (elgg_is_logged_in()) { + forward(elgg_get_logged_in_user_entity()->getURL()); } // short circuit if invalid or banned username diff --git a/mod/reportedcontent/views/default/widgets/reportedcontent/content.php b/mod/reportedcontent/views/default/widgets/reportedcontent/content.php index 4f8906ef2..4c6595653 100644 --- a/mod/reportedcontent/views/default/widgets/reportedcontent/content.php +++ b/mod/reportedcontent/views/default/widgets/reportedcontent/content.php @@ -7,6 +7,7 @@ $list = elgg_list_entities(array( 'types' => 'object', 'subtypes' => 'reported_content', 'limit' => $vars['entity']->num_display, + 'pagination' => false, )); if (!$list) { $list = '<p class="mtm">' . elgg_echo('reportedcontent:none') . '</p>'; diff --git a/mod/thewire/actions/delete.php b/mod/thewire/actions/delete.php index 58502a7e7..38355d25e 100644 --- a/mod/thewire/actions/delete.php +++ b/mod/thewire/actions/delete.php @@ -24,7 +24,7 @@ if ($thewire->getSubtype() == "thewire" && $thewire->canEdit()) { } // Get owning user - $owner = get_entity($thewire->getOwner()); + $owner = get_entity($thewire->getOwnerGUID()); // Delete it $rowsaffected = $thewire->delete(); diff --git a/mod/tinymce/README.txt b/mod/tinymce/README.txt new file mode 100644 index 000000000..2814e9390 --- /dev/null +++ b/mod/tinymce/README.txt @@ -0,0 +1,10 @@ +Adding a language +====================== +1. Download the language pack from [TinyMCE][1] +2. Extract the files from the zip file. +3. Copy the langs, plugins, and themes directories into mod/tinymce/vendor/tinymce/jscripts/tiny_mce/. +There are already directories with those names. You do not want to delete those directories. +Instead, copy the new directories on top of the old ones. +4. Flush the Elgg caches. + +[1]: http://www.tinymce.com/i18n/index.php?ctrl=lang&act=download "TinyMCE" diff --git a/mod/tinymce/activate.php b/mod/tinymce/activate.php new file mode 100644 index 000000000..6f5cc8d50 --- /dev/null +++ b/mod/tinymce/activate.php @@ -0,0 +1,14 @@ +<?php +/** + * Prompt the user to install a tinymce language after activating + */ + +if (elgg_get_config('language') != tinymce_get_site_language()) { + $message = elgg_echo('tinymce:lang_notice', array( + elgg_echo(elgg_get_config('language')), + "http://www.tinymce.com/i18n/index.php?ctrl=lang&act=download", + elgg_get_plugins_path() . "tinymce/vendor/tinymce/jscripts/tiny_mce/", + elgg_add_action_tokens_to_url(elgg_normalize_url('action/admin/site/flush_cache')), + )); + elgg_add_admin_notice('tinymce_admin_notice_no_lang', $message); +} diff --git a/mod/tinymce/languages/en.php b/mod/tinymce/languages/en.php index 811e93492..b2702549c 100644 --- a/mod/tinymce/languages/en.php +++ b/mod/tinymce/languages/en.php @@ -9,6 +9,7 @@ $english = array( 'tinymce:remove' => "Remove editor", 'tinymce:add' => "Add editor", 'tinymce:word_count' => 'Word count: ', + 'tinymce:lang_notice' => "Your site language is %s but it isn't installed for TinyMCE. Get it <a target=\"_blank\" href=\"%s\">here</a> and copy it to %s. Then, <a href=\"%s\">flush the caches</a>. See the TinyMCE README for more details.", ); -add_translation("en", $english);
\ No newline at end of file +add_translation("en", $english); diff --git a/mod/tinymce/start.php b/mod/tinymce/start.php index 48625f456..6aba837e0 100644 --- a/mod/tinymce/start.php +++ b/mod/tinymce/start.php @@ -33,3 +33,15 @@ function tinymce_longtext_menu($hook, $type, $items, $vars) { return $items; } + +function tinymce_get_site_language() { + + if ($site_language = elgg_get_config('language')) { + $path = elgg_get_plugins_path() . "tinymce/vendor/tinymce/jscripts/tiny_mce/langs"; + if (file_exists("$path/$site_language.js")) { + return $site_language; + } + } + + return 'en'; +} diff --git a/mod/tinymce/views/default/js/tinymce.php b/mod/tinymce/views/default/js/tinymce.php index e6e2865a5..51e99c223 100644 --- a/mod/tinymce/views/default/js/tinymce.php +++ b/mod/tinymce/views/default/js/tinymce.php @@ -38,6 +38,7 @@ elgg.tinymce.init = function() { mode : "specific_textareas", editor_selector : "elgg-input-longtext", theme : "advanced", + language : "<?php echo tinymce_get_site_language(); ?>", plugins : "lists,spellchecker,autosave,fullscreen,paste", relative_urls : false, remove_script_host : false, @@ -86,4 +87,4 @@ elgg.tinymce.init = function() { } } -elgg.register_hook_handler('init', 'system', elgg.tinymce.init);
\ No newline at end of file +elgg.register_hook_handler('init', 'system', elgg.tinymce.init); diff --git a/version.php b/version.php index 0fb757b9c..dda087c52 100644 --- a/version.php +++ b/version.php @@ -11,7 +11,7 @@ // YYYYMMDD = Elgg Date // XX = Interim incrementer -$version = 2012061800; +$version = 2012071100; // Human-friendly version name -$release = '1.8.6'; +$release = '1.8.8'; diff --git a/views/default/css/admin.php b/views/default/css/admin.php index 0f5c1f677..78ec95c26 100644 --- a/views/default/css/admin.php +++ b/views/default/css/admin.php @@ -25,7 +25,6 @@ table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; - outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; @@ -41,9 +40,6 @@ img { border-width: 0; border-color: transparent; } -:focus { - outline: 0 none; -} ol, ul { list-style: none; } @@ -359,6 +355,8 @@ p { .elgg-table td, .elgg-table th { background: white; border: 1px solid #ccc; + padding: 4px 8px; + vertical-align: middle; } .elgg-table th { background-color: #ddd; @@ -366,10 +364,10 @@ p { .elgg-table .alt td { background: #eee; } -.elgg-table td { - padding: 4px 8px; - border-bottom: 1px solid #ccc; +.elgg-table input[type=checkbox] { + margin-top: 3px; } + .elgg-table-alt { width: 100%; border-top: 1px solid #ccc; @@ -441,7 +439,9 @@ input { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; + margin: 0; } + /* default elgg core input field classes */ .elgg-input-text, .elgg-input-tags, @@ -471,7 +471,6 @@ textarea { width: auto; padding: 2px 4px; cursor: pointer; - outline: none; } a.elgg-button { padding: 3px 6px; diff --git a/views/default/output/location.php b/views/default/output/location.php index e3619d2e1..e1009f17d 100644 --- a/views/default/output/location.php +++ b/views/default/output/location.php @@ -11,4 +11,9 @@ if (isset($vars['entity'])) { unset($vars['entity']); } +// Fixes #4566 we used to allow arrays of strings for location +if (is_array($vars['value'])) { + $vars['value'] = implode(', ', $vars['value']); +} + echo elgg_view('output/tag', $vars); diff --git a/views/default/page/components/list.php b/views/default/page/components/list.php index 28c907ab6..0cf7d507c 100644 --- a/views/default/page/components/list.php +++ b/views/default/page/components/list.php @@ -6,7 +6,7 @@ * * @uses $vars['items'] Array of ElggEntity or ElggAnnotation objects * @uses $vars['offset'] Index of the first list item in complete list - * @uses $vars['limit'] Number of items per page + * @uses $vars['limit'] Number of items per page. Only used as input to pagination. * @uses $vars['count'] Number of items in the complete list * @uses $vars['base_url'] Base URL of list (optional) * @uses $vars['pagination'] Show pagination? (default: true) diff --git a/views/default/page/elements/comments.php b/views/default/page/elements/comments.php index cf9b5f08b..97cb9574e 100644 --- a/views/default/page/elements/comments.php +++ b/views/default/page/elements/comments.php @@ -36,8 +36,7 @@ if ($html) { } if ($show_add_form) { - $form_vars = array('name' => 'elgg_add_comment'); - echo elgg_view_form('comments/add', $form_vars, $vars); + echo elgg_view_form('comments/add', array(), $vars); } echo '</div>'; diff --git a/views/default/widgets/new_users/content.php b/views/default/widgets/new_users/content.php index 207a67a9d..ba85e7421 100644 --- a/views/default/widgets/new_users/content.php +++ b/views/default/widgets/new_users/content.php @@ -6,5 +6,6 @@ echo elgg_list_entities(array( 'type' => 'user', 'subtype'=> null, - 'full_view' => FALSE + 'full_view' => false, + 'pagination' => false, ));
\ No newline at end of file diff --git a/views/default/widgets/online_users/content.php b/views/default/widgets/online_users/content.php index d81ff3705..6e0cc7abb 100644 --- a/views/default/widgets/online_users/content.php +++ b/views/default/widgets/online_users/content.php @@ -3,4 +3,13 @@ * Online users widget */ -echo $users_online = get_online_users();
\ No newline at end of file +$count = find_active_users(600, 10, 0, true); +$objects = find_active_users(600, 10); + +if ($objects) { + echo elgg_view_entity_list($objects, array( + 'count' => $count, + 'limit' => 10, + 'pagination' => false, + )); +} |