diff --git a/phpBB/composer.lock b/phpBB/composer.lock index b6957aa667..e6dd12e8f0 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -145,7 +145,7 @@ "Psr\\Log\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -163,6 +163,63 @@ ], "time": "2012-12-21 11:40:51" }, + { + "name": "s9e/text-formatter", + "version": "dev-release/php5.3", + "source": { + "type": "git", + "url": "https://github.com/s9e/TextFormatter.git", + "reference": "872ed9d9204986668afc0b3e633be99e397e201b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/872ed9d9204986668afc0b3e633be99e397e201b", + "reference": "872ed9d9204986668afc0b3e633be99e397e201b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-filter": "*", + "php": ">=5.3.3" + }, + "suggest": { + "ext-intl": "Allows international URLs to be accepted by the URL filter", + "ext-json": "Enables the generation of a JavaScript parser", + "ext-mbstring": "Enables some optimizations in the PHP renderer", + "ext-tokenizer": "Enables optimizations in the PHP renderer", + "ext-xsl": "Enables the XSLT renderer", + "ext-zlib": "Enables gzip compression when scraping content via the MediaEmbed plugin" + }, + "type": "library", + "autoload": { + "psr-4": { + "s9e\\TextFormatter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Multi-purpose text formatting and markup library. Plugins offer support for BBCodes, Markdown, emoticons, HTML, embedding media (YouTube, etc...), enhanced typography and more.", + "keywords": [ + "bbcode", + "bbcodes", + "blog", + "censor", + "embed", + "emoji", + "emoticons", + "engine", + "forum", + "html", + "markdown", + "markup", + "media", + "parser", + "shortcodes" + ], + "time": "2014-11-22 14:23:43" + }, { "name": "symfony/config", "version": "2.7.x-dev", @@ -960,16 +1017,14 @@ "Twig_": "lib/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "email": "fabien@symfony.com" }, { "name": "Armin Ronacher", @@ -993,21 +1048,21 @@ "packages-dev": [ { "name": "fabpot/goutte", - "version": "v1.0.7", + "version": "v1.0.3", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625" + "url": "https://github.com/fabpot/Goutte.git", + "reference": "75c9f23c4122caf4ea3e87a42a00b471366e707f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/794b196e76bdd37b5155cdecbad311f0a3b07625", - "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625", + "url": "https://api.github.com/repos/fabpot/Goutte/zipball/75c9f23c4122caf4ea3e87a42a00b471366e707f", + "reference": "75c9f23c4122caf4ea3e87a42a00b471366e707f", "shasum": "" }, "require": { "ext-curl": "*", - "guzzle/http": "~3.1", + "guzzle/http": ">=3.0.5,<3.8-dev", "php": ">=5.3.0", "symfony/browser-kit": "~2.1", "symfony/css-selector": "~2.1", @@ -1016,8 +1071,8 @@ "symfony/process": "~2.1" }, "require-dev": { - "guzzle/plugin-history": "~3.1", - "guzzle/plugin-mock": "~3.1" + "guzzle/plugin-history": ">=3.0.5,<3.8-dev", + "guzzle/plugin-mock": ">=3.0.5,<3.8-dev" }, "type": "application", "extra": { @@ -1037,7 +1092,9 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" } ], "description": "A simple PHP Web Scraper", @@ -1045,7 +1102,7 @@ "keywords": [ "scraper" ], - "time": "2014-10-09 15:52:51" + "time": "2013-08-16 06:03:22" }, { "name": "guzzle/common", @@ -1376,8 +1433,7 @@ "authors": [ { "name": "Michiel Rook", - "email": "mrook@php.net", - "role": "Lead" + "email": "mrook@php.net" }, { "name": "Phing Community", @@ -1881,16 +1937,16 @@ }, { "name": "sami/sami", - "version": "v1.4", + "version": "v1.3", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/Sami.git", - "reference": "70f29c781f7bef30181c814b9471b2ceac694454" + "url": "https://github.com/fabpot/Sami.git", + "reference": "76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Sami/zipball/70f29c781f7bef30181c814b9471b2ceac694454", - "reference": "70f29c781f7bef30181c814b9471b2ceac694454", + "url": "https://api.github.com/repos/fabpot/Sami/zipball/76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110", + "reference": "76f2ed80b3420f7e2f6dcd5b7218b5a5781f4110", "shasum": "" }, "require": { @@ -1911,7 +1967,7 @@ "type": "application", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -1926,7 +1982,9 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" } ], "description": "Sami, an API documentation generator", @@ -1934,7 +1992,7 @@ "keywords": [ "phpdoc" ], - "time": "2014-06-25 11:24:03" + "time": "2013-11-30 17:16:25" }, { "name": "sebastian/comparator", diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 36f22d72d6..2b4aa52571 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -13,9 +13,9 @@ imports: - { resource: services_notification.yml } - { resource: services_password.yml } - { resource: services_profilefield.yml } + - { resource: services_text_formatter.yml } - { resource: services_twig.yml } - { resource: services_user.yml } - - { resource: tables.yml } - { resource: parameters.yml } diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml new file mode 100644 index 0000000000..7d21e4498e --- /dev/null +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -0,0 +1,58 @@ +parameters: + text_formatter.cache.dir: %core.root_path%cache/ + text_formatter.cache.parser.key: _text_formatter_parser + text_formatter.cache.renderer.key: _text_formatter_renderer + +services: + text_formatter.cache: + alias: text_formatter.s9e.factory + + text_formatter.data_access: + class: phpbb\textformatter\data_access + arguments: + - @dbal.conn + - %tables.bbcodes% + - %tables.smilies% + - %tables.styles% + - %tables.words% + - %core.root_path%styles/ + + text_formatter.parser: + alias: text_formatter.s9e.parser + + text_formatter.renderer: + alias: text_formatter.s9e.renderer + + text_formatter.utils: + alias: text_formatter.s9e.utils + + text_formatter.s9e.factory: + class: phpbb\textformatter\s9e\factory + arguments: + - @text_formatter.data_access + - @cache.driver + - %text_formatter.cache.dir% + - %text_formatter.cache.parser.key% + - %text_formatter.cache.renderer.key% + + text_formatter.s9e.parser: + class: phpbb\textformatter\s9e\parser + arguments: + - @cache.driver + - %text_formatter.cache.parser.key% + - @user + - @service_container + + text_formatter.s9e.renderer: + class: phpbb\textformatter\s9e\renderer + arguments: + - @cache.driver + - %text_formatter.cache.dir% + - %text_formatter.cache.renderer.key% + - @service_container + calls: + - [configure_smilies_path, [@config, @path_helper]] + - [configure_user, [@user, @config, @auth]] + + text_formatter.s9e.utils: + class: phpbb\textformatter\s9e\utils diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml index 2fe2a33be8..00067d5abe 100644 --- a/phpBB/config/default/container/tables.yml +++ b/phpBB/config/default/container/tables.yml @@ -1,6 +1,7 @@ parameters: tables.auth_provider_oauth_token_storage: %core.table_prefix%oauth_tokens tables.auth_provider_oauth_account_assoc: %core.table_prefix%oauth_accounts + tables.bbcodes: %core.table_prefix%bbcodes tables.captcha_qa_questions: %core.table_prefix%captcha_questions tables.captcha_qa_answers: %core.table_prefix%captcha_answers tables.captcha_qa_confirm: %core.table_prefix%qa_confirm @@ -18,6 +19,9 @@ parameters: tables.profile_fields_options_language: %core.table_prefix%profile_fields_lang tables.profile_fields_language: %core.table_prefix%profile_lang tables.posts: %core.table_prefix%posts + tables.smilies: %core.table_prefix%smilies + tables.styles: %core.table_prefix%styles tables.topics: %core.table_prefix%topics tables.user_notifications: %core.table_prefix%user_notifications tables.users: %core.table_prefix%users + tables.words: %core.table_prefix%words diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index a5cd48c444..327af0e0bc 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -269,6 +269,7 @@ class acp_bbcodes $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_ADDED'; $log_action = 'LOG_BBCODE_ADD'; @@ -280,6 +281,7 @@ class acp_bbcodes WHERE bbcode_id = ' . $bbcode_id; $db->sql_query($sql); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_EDITED'; $log_action = 'LOG_BBCODE_EDIT'; diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index fdf366097a..5d1756de45 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -28,7 +28,7 @@ class acp_icons function main($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; global $request, $phpbb_container; @@ -486,6 +486,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); $level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING; $errormsgs = ''; @@ -661,6 +662,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); } @@ -783,6 +785,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { @@ -848,6 +851,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index c49ccdf479..9a99666c75 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -352,6 +352,11 @@ class acp_main $config->increment('assets_version', 1); $cache->purge(); + // Remove old renderers from the text_formatter service. Since this + // operation is performed after the cache is purged, there is not "current" + // renderer and in effect all renderers will be purged + $phpbb_container->get('text_formatter.cache')->tidy(); + // Clear permissions $auth->acl_clear_prefetch(); phpbb_cache_moderators($db, $cache, $auth); diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index d28aa8e60b..1ba247be4d 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -115,6 +115,7 @@ class acp_words } $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; @@ -148,6 +149,7 @@ class acp_words $db->sql_query($sql); $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($deleted_word)); diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index bdbc8a92fa..60511d89a4 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -389,46 +389,68 @@ function phpbb_clean_search_string($search_string) /** * Decode text whereby text is coming from the db and expected to be pre-parsed content * We are placing this outside of the message parser because we are often in need of it... +* +* NOTE: special chars are kept encoded +* +* @param string &$message Original message, passed by reference +* @param string $bbcode_uid BBCode UID +* @return null */ function decode_message(&$message, $bbcode_uid = '') { - global $config; + global $phpbb_container; - if ($bbcode_uid) + if (preg_match('#^<[rt][ >]#', $message)) { - $match = array('
', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); - $replace = array("\n", '', '', '', ''); + $message = htmlspecialchars($phpbb_container->get('text_formatter.utils')->unparse($message), ENT_COMPAT); } else { - $match = array('
'); - $replace = array("\n"); + if ($bbcode_uid) + { + $match = array('
', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); + $replace = array("\n", '', '', '', ''); + } + else + { + $match = array('
'); + $replace = array("\n"); + } + + $message = str_replace($match, $replace, $message); + + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); + + $message = preg_replace($match, $replace, $message); } - - $message = str_replace($match, $replace, $message); - - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); - - $message = preg_replace($match, $replace, $message); } /** -* Strips all bbcode from a text and returns the plain content +* Strips all bbcode from a text in place */ function strip_bbcode(&$text, $uid = '') { - if (!$uid) + global $phpbb_container; + + if (preg_match('#^<[rt][ >]#', $text)) { - $uid = '[0-9a-z]{5,}'; + $text = $phpbb_container->get('text_formatter.utils')->clean_formatting($text); } + else + { + if (!$uid) + { + $uid = '[0-9a-z]{5,}'; + } - $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); + $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); - $text = preg_replace($match, $replace, $text); + $text = preg_replace($match, $replace, $text); + } } /** @@ -438,7 +460,7 @@ function strip_bbcode(&$text, $uid = '') function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text = true) { static $bbcode; - global $phpbb_dispatcher; + global $phpbb_dispatcher, $phpbb_container; if ($text === '') { @@ -459,35 +481,57 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text $vars = array('text', 'uid', 'bitfield', 'flags', 'censor_text'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_display_before', compact($vars))); - if ($censor_text) + if (preg_match('#^<[rt][ >]#', $text)) { - $text = censor_text($text); - } + $renderer = $phpbb_container->get('text_formatter.renderer'); - // Parse bbcode if bbcode uid stored and bbcode enabled - if ($uid && ($flags & OPTION_FLAG_BBCODE)) + // Temporarily switch off viewcensors if applicable + $old_censor = $renderer->get_viewcensors(); + if ($old_censor !== $censor_text) + { + $renderer->set_viewcensors($censor_text); + } + + $text = $renderer->render($text); + + // Restore the previous value + if ($old_censor !== $censor_text) + { + $renderer->set_viewcensors($old_censor); + } + } + else { - if (!class_exists('bbcode')) + if ($censor_text) { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $text = censor_text($text); } - if (empty($bbcode)) + // Parse bbcode if bbcode uid stored and bbcode enabled + if ($uid && ($flags & OPTION_FLAG_BBCODE)) { - $bbcode = new bbcode($bitfield); - } - else - { - $bbcode->bbcode($bitfield); + if (!class_exists('bbcode')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + } + + if (empty($bbcode)) + { + $bbcode = new bbcode($bitfield); + } + else + { + $bbcode->bbcode($bitfield); + } + + $bbcode->bbcode_second_pass($text, $uid); } - $bbcode->bbcode_second_pass($text, $uid); + $text = bbcode_nl2br($text); + $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); } - $text = bbcode_nl2br($text); - $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); - /** * Use this event to modify the text after it is parsed * @@ -550,11 +594,6 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb $uid = $bitfield = ''; $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0); - if ($text === '') - { - return; - } - if (!class_exists('parse_message')) { include($phpbb_root_path . 'includes/message_parser.' . $phpEx); diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index ccb953adbe..e4c35f8bca 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1094,7 +1094,7 @@ class parse_message extends bbcode_firstpass function parse_message($message = '') { // Init BBCode UID - $this->bbcode_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN); + $this->bbcode_uid = ''; $this->message = $message; } @@ -1103,7 +1103,7 @@ class parse_message extends bbcode_firstpass */ function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post') { - global $config, $db, $user, $phpbb_dispatcher; + global $config, $db, $user, $phpbb_dispatcher, $phpbb_container; $this->mode = $mode; @@ -1132,12 +1132,6 @@ class parse_message extends bbcode_firstpass $this->decode_message(); } - // Do some general 'cleanup' first before processing message, - // e.g. remove excessive newlines(?), smilies(?) - $match = array('#(script|about|applet|activex|chrome):#i'); - $replace = array("\\1:"); - $this->message = preg_replace($match, $replace, trim($this->message)); - // Store message length... $message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)); @@ -1210,47 +1204,29 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Prepare BBcode (just prepares some tags for better parsing) - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->bbcode_init(); - $disallow = array('img', 'flash', 'quote', 'url'); - foreach ($disallow as $bool) - { - if (!${'allow_' . $bool . '_bbcode'}) - { - $this->bbcodes[$bool]['disabled'] = true; - } - } + // Get the parser + $parser = $phpbb_container->get('text_formatter.parser'); - $this->prepare_bbcodes(); - } + // Set the parser's options + ($allow_bbcode) ? $parser->enable_bbcodes() : $parser->disable_bbcodes(); + ($allow_magic_url) ? $parser->enable_magic_url() : $parser->disable_magic_url(); + ($allow_smilies) ? $parser->enable_smilies() : $parser->disable_smilies(); + ($allow_img_bbcode) ? $parser->enable_bbcode('img') : $parser->disable_bbcode('img'); + ($allow_flash_bbcode) ? $parser->enable_bbcode('flash') : $parser->disable_bbcode('flash'); + ($allow_quote_bbcode) ? $parser->enable_bbcode('quote') : $parser->disable_bbcode('quote'); + ($allow_url_bbcode) ? $parser->enable_bbcode('url') : $parser->disable_bbcode('url'); - // Parse smilies - if ($allow_smilies) - { - $this->smilies($config['max_' . $mode . '_smilies']); - } + // Set some config values + $parser->set_vars(array( + 'max_font_size' => $config['max_' . $this->mode . '_font_size'], + 'max_img_height' => $config['max_' . $this->mode . '_img_height'], + 'max_img_width' => $config['max_' . $this->mode . '_img_width'], + 'max_smilies' => $config['max_' . $this->mode . '_smilies'], + 'max_urls' => $config['max_' . $this->mode . '_urls'] + )); - $num_urls = 0; - - // Parse BBCode - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->parse_bbcode(); - $num_urls += $this->parsed_items['url']; - } - - // Parse URL's - if ($allow_magic_url) - { - $this->magic_url(generate_board_url()); - - if ($config['max_' . $mode . '_urls']) - { - $num_urls += preg_match_all('#\(.*?)#s', $template, $matches, PREG_SET_ORDER); + + $fragments = array(); + foreach ($matches as $match) + { + // Normalize the whitespace + $fragment = preg_replace('#>\\n\\t*<#', '><', trim($match[2])); + + $fragments[$match[1]] = $fragment; + } + + // Automatically recompose templates split between *_open and *_close + foreach ($fragments as $fragment_name => $fragment) + { + if (preg_match('#^(\\w+)_close$#', $fragment_name, $match)) + { + $bbcode_name = $match[1]; + + if (isset($fragments[$bbcode_name . '_open'])) + { + $templates[$bbcode_name] = $fragments[$bbcode_name . '_open'] . '' . $fragment; + } + } + } + + // Manually recompose and overwrite irregular templates + $templates['list'] = + ' + + ' . $fragments['ulist_open_default'] . '' . $fragments['ulist_close'] . ' + + + ' . $fragments['olist_open'] . '' . $fragments['olist_close'] . ' + + + ' . $fragments['ulist_open'] . '' . $fragments['ulist_close'] . ' + + '; + + $templates['li'] = $fragments['listitem'] . '' . $fragments['listitem_close']; + + $templates['quote'] = + ' + + ' . $fragments['quote_username_open'] . '' . $fragments['quote_close'] . ' + + + ' . $fragments['quote_open'] . '' . $fragments['quote_close'] . ' + + '; + + // The [attachment] BBCode uses the inline_attachment template to output a comment that + // is post-processed by parse_attachments() + $templates['attachment'] = $fragments['inline_attachment_open'] . ' ia ia ' . $fragments['inline_attachment_close']; + + // Finally save fragments whose names look like the name of a BBCode, e.g. "flash" + foreach ($fragments as $fragment_name => $fragment) + { + if (preg_match('#^\\w+$#', $fragment_name)) + { + $templates[$fragment_name] = $fragment; + } + } + + return $templates; + } + + /** + * Merge the templates from any number of styles into one BBCode template + * + * @param array $style_templates Associative array matching style_ids to their template + * @return string + */ + protected function merge_templates(array $style_templates) + { + // Group identical templates together + $grouped_templates = array(); + foreach ($style_templates as $style_id => $style_template) + { + $grouped_templates[$style_template][] = $style_id; + } + + if (count($grouped_templates) === 1) + { + return $style_template; + } + + // Sort templates by frequency descending + $templates_cnt = array_map('sizeof', $grouped_templates); + array_multisort($grouped_templates, $templates_cnt); + + // Remove the most frequent template from the list; It becomes the default + reset($grouped_templates); + $default_template = key($grouped_templates); + unset($grouped_templates[$default_template]); + + // Build an xsl:choose switch + $template = ''; + foreach ($grouped_templates as $style_template => $style_ids) + { + $template .= '' . $style_template . ''; + } + $template .= '' . $default_template . ''; + + return $template; + } +} diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php new file mode 100644 index 0000000000..10e33f47e6 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -0,0 +1,335 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\textformatter\s9e; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use s9e\TextFormatter\Parser\BuiltInFilters; +use s9e\TextFormatter\Parser\Logger; + +/** +* s9e\TextFormatter\Parser adapter +* @package phpBB3 +*/ +class parser extends \phpbb\textformatter\parser +{ + /** + * @var s9e\TextFormatter\Parser + */ + protected $parser; + + /** + * @var phpbb\user User object, used for translating errors + */ + protected $user; + + /** + * Constructor + * + * @param phpbb\cache\driver_interface $cache + * @param string $key Cache key + * @param phpbb\user $user + * @param Symfony\Component\DependencyInjection\ContainerInterface $container + * @return null + */ + public function __construct(\phpbb\cache\driver\driver_interface $cache, $key, \phpbb\user $user, ContainerInterface $container) + { + $this->user = $user; + + $parser = $cache->get($key); + if (!$parser) + { + list($parser) = $container->get('text_formatter.s9e.factory')->regenerate(); + } + + $this->parser = $parser; + } + + /** + * {@inheritdoc} + */ + public function parse($text) + { + return $this->parser->parse($text); + } + + /** + * {@inheritdoc} + */ + public function disable_bbcode($name) + { + $this->parser->disableTag(strtoupper($name)); + } + + /** + * {@inheritdoc} + */ + public function disable_bbcodes() + { + $this->parser->disablePlugin('BBCodes'); + } + + /** + * {@inheritdoc} + */ + public function disable_censor() + { + $this->parser->disablePlugin('Censor'); + } + + /** + * {@inheritdoc} + */ + public function disable_magic_url() + { + $this->parser->disablePlugin('Autoemail'); + $this->parser->disablePlugin('Autolink'); + } + + /** + * {@inheritdoc} + */ + public function disable_smilies() + { + $this->parser->disablePlugin('Emoticons'); + } + + /** + * {@inheritdoc} + */ + public function enable_bbcode($name) + { + $this->parser->enableTag(strtoupper($name)); + } + + /** + * {@inheritdoc} + */ + public function enable_bbcodes() + { + $this->parser->enablePlugin('BBCodes'); + } + + /** + * {@inheritdoc} + */ + public function enable_censor() + { + $this->parser->enablePlugin('Censor'); + } + + /** + * {@inheritdoc} + */ + public function enable_magic_url() + { + $this->parser->enablePlugin('Autoemail'); + $this->parser->enablePlugin('Autolink'); + } + + /** + * {@inheritdoc} + */ + public function enable_smilies() + { + $this->parser->enablePlugin('Emoticons'); + } + + /** + * {@inheritdoc} + * + * This will translate the log entries found in s9e\TextFormatter's logger into phpBB error + * messages + */ + public function get_errors() + { + $errors = array(); + + foreach ($this->parser->getLogger()->get() as $entry) + { + list($type, $msg, $context) = $entry; + + if ($msg === 'Tag limit exceeded') + { + if ($context['tagName'] === 'E') + { + $errors[] = $this->user->lang('TOO_MANY_SMILIES', $context['tagLimit']); + } + else if ($context['tagName'] === 'URL') + { + $errors[] = $this->user->lang('TOO_MANY_URLS', $context['tagLimit']); + } + } + else if ($msg === 'MAX_FONT_SIZE_EXCEEDED') + { + $errors[] = $this->user->lang($msg, $context['max_size']); + } + else if (preg_match('/^MAX_(?:FLASH|IMG)_(HEIGHT|WIDTH)_EXCEEDED$/D', $msg, $m)) + { + $errors[] = $this->user->lang($msg, $context['max_' . strtolower($m[1])]); + } + else if ($msg === 'Tag is disabled') + { + $name = strtolower($context['tag']->getName()); + $errors[] = $this->user->lang('UNAUTHORISED_BBCODE', '[' . $name . ']'); + } + else if ($msg === 'UNABLE_GET_IMAGE_SIZE') + { + $errors[] = $this->user->lang[$msg]; + } + } + + return array_unique($errors); + } + + /** + * {@inheritdoc} + */ + public function set_var($name, $value) + { + if ($name === 'max_smilies') + { + $this->parser->setTagLimit('E', $value ?: PHP_INT_MAX); + } + else if ($name === 'max_urls') + { + $this->parser->setTagLimit('URL', $value ?: PHP_INT_MAX); + } + else + { + $this->parser->registeredVars[$name] = $value; + } + } + + /** + * Filter a flash object's height + * + * @see bbcode_firstpass::bbcode_flash() + * + * @param string $height + * @param integer $max_height + * @param s9e\TextFormatter\Parser\Logger $logger + * @return mixed Original value if valid, FALSE otherwise + */ + static public function filter_flash_height($height, $max_height, Logger $logger) + { + if ($max_height && $height > $max_height) + { + $logger->err('MAX_FLASH_HEIGHT_EXCEEDED', array('max_height' => $max_height)); + + return false; + } + + return $height; + } + + /** + * Filter a flash object's width + * + * @see bbcode_firstpass::bbcode_flash() + * + * @param string $width + * @param integer $max_width + * @param s9e\TextFormatter\Parser\Logger $logger + * @return mixed Original value if valid, FALSE otherwise + */ + static public function filter_flash_width($width, $max_width, Logger $logger) + { + if ($max_width && $width > $max_width) + { + $logger->err('MAX_FLASH_WIDTH_EXCEEDED', array('max_width' => $max_width)); + + return false; + } + + return $width; + } + + /** + * Filter the value used in a [size] BBCode + * + * @see bbcode_firstpass::bbcode_size() + * + * @param string $size Original size + * @param integer $max_size Maximum allowed size + * @param s9e\TextFormatter\Parser\Logger $logger + * @return mixed Original value if valid, FALSE otherwise + */ + static public function filter_font_size($size, $max_size, Logger $logger) + { + if ($max_size && $size > $max_size) + { + $logger->err('MAX_FONT_SIZE_EXCEEDED', array('max_size' => $max_size)); + + return false; + } + + if ($size < 1) + { + return false; + } + + return $size; + } + + /** + * Filter an image's URL to enforce restrictions on its dimensions + * + * @see bbcode_firstpass::bbcode_img() + * + * @param string $url Original URL + * @param array $url_config Config used by the URL filter + * @param s9e\TextFormatter\Parser\Logger $logger + * @param integer $max_height Maximum height allowed + * @param integer $max_width Maximum width allowed + * @return string|bool Original value if valid, FALSE otherwise + */ + static public function filter_img_url($url, array $url_config, Logger $logger, $max_height, $max_width) + { + // Validate the URL + $url = BuiltInFilters::filterUrl($url, $url_config, $logger); + + if ($url === false) + { + return false; + } + + if ($max_height || $max_width) + { + $stats = @getimagesize($url); + + if ($stats === false) + { + $logger->err('UNABLE_GET_IMAGE_SIZE'); + + return false; + } + + if ($max_height && $max_height < $stats[1]) + { + $logger->err('MAX_IMG_HEIGHT_EXCEEDED', array('max_height' => $max_height)); + + return false; + } + + if ($max_width && $max_width < $stats[0]) + { + $logger->err('MAX_IMG_WIDTH_EXCEEDED', array('max_width' => $max_width)); + + return false; + } + } + + return $url; + } +} diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php new file mode 100644 index 0000000000..2c8412f961 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -0,0 +1,228 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\textformatter\s9e; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** +* s9e\TextFormatter\Renderer adapter +* @package phpBB3 +*/ +class renderer extends \phpbb\textformatter\renderer +{ + /** + * @var s9e\TextFormatter\Renderer + */ + protected $renderer; + + /** + * @var bool Status of the viewcensors option + */ + protected $viewcensors = false; + + /** + * @var bool Status of the viewflash option + */ + protected $viewflash = false; + + /** + * @var bool Status of the viewimg option + */ + protected $viewimg = false; + + /** + * @var bool Status of the viewsmilies option + */ + protected $viewsmilies = false; + + /** + * Constructor + * + * @param phpbb\cache\driver\driver_interface $cache + * @param string $cache_dir Path to the cache dir + * @param string $key Cache key + * @param Symfony\Component\DependencyInjection\ContainerInterface $container + * @return null + */ + public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_dir, $key, ContainerInterface $container) + { + $renderer_data = $cache->get($key); + + if ($renderer_data) + { + $class = $renderer_data['class']; + + if (!class_exists($class, false)) + { + // Try to load the renderer class from its cache file + $cache_file = $cache_dir . $class . '.php'; + + if (file_exists($cache_file)) + { + include($cache_file); + } + } + + if (class_exists($class, false)) + { + $renderer = unserialize($renderer_data['renderer']); + } + } + + if (!isset($renderer)) + { + list(, $renderer) = $container->get('text_formatter.s9e.factory')->regenerate(); + } + + $this->renderer = $renderer; + } + + /** + * {@inheritdoc} + */ + public function configure_user(\phpbb\user $user, \phpbb\config\config $config, \phpbb\auth\auth $auth) + { + parent::configure_user($user, $config, $auth); + + // Set the stylesheet parameters + foreach (array_keys($this->renderer->getParameters()) as $param_name) + { + if (substr($param_name, 0, 2) === 'L_') + { + // L_FOO is set to $user->lang('FOO') + $this->renderer->setParameter($param_name, $user->lang(substr($param_name, 2))); + } + } + + // Set the style id + $this->renderer->setParameter('STYLE_ID', $user->style['style_id']); + } + + /** + * {@inheritdoc} + */ + public function get_viewcensors() + { + return $this->viewcensors; + } + + /** + * {@inheritdoc} + */ + public function get_viewflash() + { + return $this->viewflash; + } + + /** + * {@inheritdoc} + */ + public function get_viewimg() + { + return $this->viewimg; + } + + /** + * {@inheritdoc} + */ + public function get_viewsmilies() + { + return $this->viewsmilies; + } + + /** + * {@inheritdoc} + */ + public function render($text) + { + $html = $this->renderer->render($text); + + /** + * @see bbcode::bbcode_second_pass_code() + */ + $html = preg_replace_callback( + '#()(.*?)()#is', + function ($captures) + { + $code = $captures[2]; + + $code = str_replace("\t", '   ', $code); + $code = str_replace(' ', '  ', $code); + $code = str_replace(' ', '  ', $code); + $code = str_replace("\n ", "\n ", $code); + + // keep space at the beginning + if (!empty($code) && $code[0] == ' ') + { + $code = ' ' . substr($code, 1); + } + + // remove newline at the beginning + if (!empty($code) && $code[0] == "\n") + { + $code = substr($code, 1); + } + + return $captures[1] . $code . $captures[3]; + }, + $html + ); + + return $html; + } + + /** + * {@inheritdoc} + */ + public function set_smilies_path($path) + { + $this->renderer->setParameter('T_SMILIES_PATH', $path); + } + + /** + * {@inheritdoc} + */ + public function set_viewcensors($value) + { + $this->viewcensors = $value; + $this->renderer->setParameter('S_VIEWCENSORS', $value); + } + + /** + * {@inheritdoc} + */ + public function set_viewflash($value) + { + $this->viewflash = $value; + $this->renderer->setParameter('S_VIEWFLASH', $value); + } + + /** + * {@inheritdoc} + */ + public function set_viewimg($value) + { + $this->viewimg = $value; + $this->renderer->setParameter('S_VIEWIMG', $value); + } + + /** + * {@inheritdoc} + */ + public function set_viewsmilies($value) + { + $this->viewsmilies = $value; + $this->renderer->setParameter('S_VIEWSMILIES', $value); + } +} diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php new file mode 100644 index 0000000000..19cd3a11c8 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/utils.php @@ -0,0 +1,67 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\textformatter\s9e; + +/** +* Text manipulation utilities +* @package phpBB3 +*/ +class utils extends \phpbb\textformatter\utils +{ + /** + * {@inheritdoc} + */ + public function clean_formatting($text) + { + // Insert a space before and then remove formatting + $text = preg_replace('#<[es]>#', ' $0', $text); + + return \s9e\TextFormatter\Unparser::removeFormatting($text); + } + + /** + * {@inheritdoc} + */ + public function remove_bbcode($text, $bbcode_name, $depth = 0) + { + $dom = new \DOMDocument; + $dom->loadXML($text); + + $xpath = new \DOMXPath($dom); + $nodes = $xpath->query(str_repeat('//' . strtoupper($bbcode_name), 1 + $depth)); + + foreach ($nodes as $node) + { + $node->parentNode->removeChild($node); + } + + return $dom->saveXML($dom->documentElement); + } + + /** + * {@inheritdoc} + */ + public function remove_formatting($text) + { + return \s9e\TextFormatter\Unparser::removeFormatting($text); + } + + /** + * {@inheritdoc} + */ + public function unparse($text) + { + return \s9e\TextFormatter\Unparser::unparse($text); + } +} diff --git a/phpBB/phpbb/textformatter/utils.php b/phpBB/phpbb/textformatter/utils.php new file mode 100644 index 0000000000..c9bed94553 --- /dev/null +++ b/phpBB/phpbb/textformatter/utils.php @@ -0,0 +1,62 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\textformatter; + +/** +* text_formatter.utils service +* +* Used to manipulate a parsed text +* +* @package phpBB3 +*/ +abstract class utils +{ + /** + * Replace BBCodes and other formatting elements with whitespace + * + * NOTE: preserves smilies as text + * + * @param string $text + * @return string + */ + abstract public function clean_formatting($text); + + /** + * Remove given BBCode at given nesting depth + * + * @param string $text Parsed text + * @param string $bbcode_name BBCode's name + * @param integer $depth Minimum nesting depth (number of parents of the same name) + * @return string + */ + abstract public function remove_bbcode($text, $bbcode_name, $depth = 0); + + /** + * Remove BBCodes and other formatting from a parsed text + * + * NOTE: preserves smilies as text + * + * @param string $text + * @return string + */ + abstract public function remove_formatting($text); + + /** + * Return a parsed text to its original form + * + * @param string $text + * @return string + */ + abstract public function unparse($text); +} diff --git a/tests/notification/group_request_test.php b/tests/notification/group_request_test.php index 0d532882c6..6a56a38c45 100644 --- a/tests/notification/group_request_test.php +++ b/tests/notification/group_request_test.php @@ -51,6 +51,7 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas )); $phpbb_dispatcher = new phpbb_mock_event_dispatcher; $phpbb_log = new \phpbb\log\null(); + $this->get_test_case_helpers()->set_s9e_services(); // Now on to the actual test diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index dee70ad016..d0b1573e61 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -11,6 +11,8 @@ * */ +use Symfony\Component\DependencyInjection\ContainerInterface; + class phpbb_test_case_helpers { protected $expectedTriggerError = false; @@ -298,4 +300,212 @@ class phpbb_test_case_helpers } } } + + /** + * Set working instances of the text_formatter.* services + * + * If no container is passed, the global $phpbb_container will be used and/or + * created if applicable + * + * @param ContainerInterface $container Service container + * @param string $fixture Path to the XML fixture + * @param string $styles_path Path to the styles dir + * @return ContainerInterface + */ + public function set_s9e_services(ContainerInterface $container = null, $fixture = null, $styles_path = null) + { + static $first_run; + global $phpbb_container, $phpbb_root_path, $phpEx; + + $cache_dir = __DIR__ . '/../tmp/'; + + // Remove old cache files on first run + if (!isset($first_run)) + { + $first_run = 1; + + array_map('unlink', array_merge( + glob($cache_dir . 'data_s9e_*'), + glob($cache_dir . 's9e_*') + )); + } + + if (!isset($container)) + { + if (!isset($phpbb_container)) + { + $phpbb_container = new phpbb_mock_container_builder; + } + + $container = $phpbb_container; + } + + if (!isset($fixture)) + { + $fixture = __DIR__ . '/../text_formatter/s9e/fixtures/default_formatting.xml'; + } + + if (!isset($styles_path)) + { + $styles_path = $phpbb_root_path . 'styles/'; + } + + $dataset = new DOMDocument; + $dataset->load($fixture); + + $tables = array( + 'phpbb_bbcodes' => array(), + 'phpbb_smilies' => array(), + 'phpbb_styles' => array(), + 'phpbb_words' => array() + ); + foreach ($dataset->getElementsByTagName('table') as $table) + { + $name = $table->getAttribute('name'); + $columns = array(); + + foreach ($table->getElementsByTagName('column') as $column) + { + $columns[] = $column->textContent; + } + + foreach ($table->getElementsByTagName('row') as $row) + { + $values = array(); + + foreach ($row->getElementsByTagName('value') as $value) + { + $values[] = $value->textContent; + } + + $tables[$name][] = array_combine($columns, $values); + } + } + + // Set up a default style if there's none set + if (empty($tables['phpbb_styles'])) + { + $tables['phpbb_styles'][] = array( + 'style_id' => 1, + 'style_path' => 'prosilver', + 'bbcode_bitfield' => 'kNg=' + ); + } + + // Mock the DAL, make it return data from the fixture + $mb = $this->test_case->getMockBuilder('phpbb\\textformatter\\data_access'); + $mb->setMethods(array('get_bbcodes', 'get_smilies', 'get_styles', 'get_words')); + $mb->setConstructorArgs(array( + $this->test_case->getMock('phpbb\\db\\driver\\driver'), + 'phpbb_bbcodes', + 'phpbb_smilies', + 'phpbb_styles', + 'phpbb_words', + $styles_path + )); + + $dal = $mb->getMock(); + $container->set('text_formatter.data_access', $dal); + + $dal->expects($this->test_case->any()) + ->method('get_bbcodes') + ->will($this->test_case->returnValue($tables['phpbb_bbcodes'])); + $dal->expects($this->test_case->any()) + ->method('get_smilies') + ->will($this->test_case->returnValue($tables['phpbb_smilies'])); + $dal->expects($this->test_case->any()) + ->method('get_styles') + ->will($this->test_case->returnValue($tables['phpbb_styles'])); + $dal->expects($this->test_case->any()) + ->method('get_words') + ->will($this->test_case->returnValue($tables['phpbb_words'])); + + // Cache the parser and renderer with a key based on this method's arguments + $cache = new \phpbb\cache\driver\file($cache_dir); + $prefix = '_s9e_' . md5(serialize(func_get_args())); + $cache_key_parser = $prefix . '_parser'; + $cache_key_renderer = $prefix . '_renderer'; + + // Create a path_helper + if (!$container->has('path_helper')) + { + $container->set( + 'path_helper', + new \phpbb\path_helper( + new \phpbb\symfony_request( + new phpbb_mock_request() + ), + new \phpbb\filesystem(), + $this->test_case->getMock('\phpbb\request\request'), + $phpbb_root_path, + $phpEx + ) + ); + } + + // Create and register the text_formatter.s9e.factory service + $factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $cache_dir, $cache_key_parser, $cache_key_renderer); + $container->set('text_formatter.s9e.factory', $factory); + + // Create a user if none was provided, and add the common lang strings + if ($container->has('user')) + { + $user = $container->get('user'); + } + else + { + $user = new \phpbb\user('\phpbb\datetime'); + $user->optionset('viewcensors', true); + $user->optionset('viewflash', true); + $user->optionset('viewimg', true); + $user->optionset('viewsmilies', true); + } + $user->add_lang('common'); + + if (!isset($user->style)) + { + $user->style = array('style_id' => 1); + } + + // Create and register the text_formatter.s9e.parser service and its alias + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + $cache_key_parser, + $user, + $container + ); + + $container->set('text_formatter.parser', $parser); + $container->set('text_formatter.s9e.parser', $parser); + + // Create and register the text_formatter.s9e.renderer service and its alias + $renderer = new \phpbb\textformatter\s9e\renderer( + $cache, + $cache_dir, + $cache_key_renderer, + $container + ); + + $root_path = ($container->hasParameter('core.root_path')) + ? $container->getParameter('core.root_path') + : './'; + $config = ($container->has('config')) + ? $container->get('config') + : new \phpbb\config\config(array('smilies_path' => 'images/smilies', 'allow_nocensors' => false)); + $auth = ($container->has('auth')) ? $container->get('auth') : new \phpbb\auth\auth; + + // Calls configured in services.yml + $renderer->configure_smilies_path($config, $container->get('path_helper')); + $renderer->configure_user($user, $config, $auth); + + $container->set('text_formatter.renderer', $renderer); + $container->set('text_formatter.s9e.renderer', $renderer); + + // Create and register the text_formatter.s9e.utils service and its alias + $utils = new \phpbb\textformatter\s9e\utils; + $container->set('text_formatter.utils', $utils); + $container->set('text_formatter.s9e.utils', $utils); + + return $container; + } } diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php new file mode 100644 index 0000000000..be258868dd --- /dev/null +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -0,0 +1,200 @@ +get_test_case_helpers()->set_s9e_services(null, $fixture); + + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $parsed_text = $parser->parse($original); + + $this->assertSame($expected, $renderer->render($parsed_text)); + } + + public function get_default_formatting_tests() + { + return array( + array( + '[b]bold[/b]', + 'bold' + ), + array( + '[u]underlined[/u]', + 'underlined' + ), + array( + '[i]italic[/i]', + 'italic' + ), + array( + '[color=#FF0000]colored[/color]', + 'colored' + ), + array( + '[color=red]colored[/color]', + 'colored' + ), + array( + '[size=75]smaller[/size]', + 'smaller' + ), + array( + '[quote]quoted[/quote]', + '
quoted
' + ), + array( + '[quote="username"]quoted[/quote]', + '
username wrote:quoted
' + ), + array( + '[code]unparsed code[/code]', + '

CODE: Select all

unparsed code
' + ), + array( + '[list]no item[/list]', + '
    ' + ), + array( + '[*]unparsed', + '[*]unparsed' + ), + array( + '[list][*]item[/list]', + '
    • item
    ' + ), + array( + '[list][*]item[/*][/list]', + '
    • item
    ' + ), + array( + '[list=1][*]item[/list]', + '
    1. item
    ' + ), + array( + '[list=a][*]item[/list]', + '
    1. item
    ' + ), + array( + '[list=i][*]item[/list]', + '
    1. item
    ' + ), + array( + '[list=I][*]item[/list]', + '
    1. item
    ' + ), + array( + '[list=disc][*]item[/list]', + '
    • item
    ' + ), + array( + '[list=circle][*]item[/list]', + '
    • item
    ' + ), + array( + '[list=square][*]item[/list]', + '
    • item
    ' + ), + array( + '[img]https://area51.phpbb.com/images/area51.png[/img]', + 'Image' + ), + array( + '[url]https://area51.phpbb.com/[/url]', + 'https://area51.phpbb.com/' + ), + array( + '[url=https://area51.phpbb.com/]Area51[/url]', + 'Area51' + ), + array( + '[email]bbcode-test@phpbb.com[/email]', + 'bbcode-test@phpbb.com' + ), + array( + '[email=bbcode-test@phpbb.com]Email[/email]', + 'Email' + ), + array( + '[attachment=0]filename[/attachment]', + '
    filename
    ' + ), + array( + // PHPBB3-1401 - correct: parsed + '[quote="[test]test"]test [ test[/quote]', + '
    [test]test wrote:test [ test
    ' + ), + array( + // PHPBB3-6117 - correct: parsed + '[quote]test[/quote] test ] and [ test [quote]test[/quote]', + '
    test
    test ] and [ test
    test
    ' + ), + array( + // PHPBB3-6200 - correct: parsed + '[quote="["]test[/quote]', + '
    [ wrote:test
    ' + ), + array( + // PHPBB3-9364 - quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted + '[quote]test[/[/b]quote] test [/quote][/quote] test', + '
    test[/[/b]quote] test
    [/quote] test' + ), + array( + // PHPBB3-8096 - first quote tag parsed, second quote tag unparsed + '[quote="a"]a[/quote][quote="a]a[/quote]', + '
    a wrote:a
    [quote="a]a[/quote]' + ), + array( + // Allow textual bbcodes in textual bbcodes + '[b]bold [i]bold + italic[/i][/b]', + 'bold bold + italic' + ), + array( + // Allow textual bbcodes in url with description + '[url=https://area51.phpbb.com/]Area51 [i]italic[/i][/url]', + 'Area51 italic' + ), + array( + // Allow url with description in textual bbcodes + '[i]italic [url=https://area51.phpbb.com/]Area51[/url][/i]', + 'italic Area51' + ), + array( + // Do not parse textual bbcodes in code + '[code]unparsed code [b]bold [i]bold + italic[/i][/b][/code]', + '

    CODE: Select all

    unparsed code [b]bold [i]bold + italic[/i][/b]
    ' + ), + array( + // Do not parse quote bbcodes in code + '[code]unparsed code [quote="username"]quoted[/quote][/code]', + '

    CODE: Select all

    unparsed code [quote="username"]quoted[/quote]
    ' + ), +/* + array( + // Textual bbcode nesting into textual bbcode + '[b]bold [i]bold + italic[/b] italic[/i]', + 'bold bold + italic italic' + ), +*/ + array( + "[code]\tline1\n line2[/code]", + '

    CODE: Select all

       line1
    ' . "\n" . '  line2
    ' + ), + ); + } +} diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php new file mode 100644 index 0000000000..2ea4b3031b --- /dev/null +++ b/tests/text_formatter/s9e/factory_test.php @@ -0,0 +1,182 @@ +createXMLDataSet(__DIR__ . '/fixtures/factory.xml'); + } + + public function get_cache_dir() + { + return __DIR__ . '/../../tmp/'; + } + + public function get_factory() + { + global $phpbb_root_path; + + $this->cache = new phpbb_mock_cache; + + $dal = new \phpbb\textformatter\data_access( + $this->new_dbal(), + 'phpbb_bbcodes', + 'phpbb_smilies', + 'phpbb_styles', + 'phpbb_words', + $phpbb_root_path . 'styles/' + ); + + $factory = new \phpbb\textformatter\s9e\factory( + $dal, + $this->cache, + $this->get_cache_dir(), + '_foo_parser', + '_foo_renderer' + ); + + return $factory; + } + + public function test_get_configurator() + { + $configurator = $this->get_factory()->get_configurator(); + + $this->assertInstanceOf('s9e\\TextFormatter\\Configurator', $configurator); + + $this->assertTrue(isset($configurator->plugins['Autoemail'])); + $this->assertTrue(isset($configurator->plugins['Autolink'])); + + $this->assertTrue(isset($configurator->BBCodes['B'])); + $this->assertTrue(isset($configurator->BBCodes['CODE'])); + $this->assertTrue(isset($configurator->BBCodes['COLOR'])); + $this->assertTrue(isset($configurator->BBCodes['EMAIL'])); + $this->assertTrue(isset($configurator->BBCodes['FLASH'])); + $this->assertTrue(isset($configurator->BBCodes['I'])); + $this->assertTrue(isset($configurator->BBCodes['IMG'])); + $this->assertTrue(isset($configurator->BBCodes['LIST'])); + $this->assertTrue(isset($configurator->BBCodes['*'])); + $this->assertTrue(isset($configurator->BBCodes['QUOTE'])); + $this->assertTrue(isset($configurator->BBCodes['SIZE'])); + $this->assertTrue(isset($configurator->BBCodes['U'])); + $this->assertTrue(isset($configurator->BBCodes['URL'])); + + // This custom BBCode should be set + $this->assertTrue(isset($configurator->BBCodes['CUSTOM'])); + + // This unsafe custom BBCode will trigger an exception and should be ignored + $this->assertFalse(isset($configurator->BBCodes['UNSAFE'])); + + $this->assertTrue(isset($configurator->Emoticons[':D'])); + } + + public function test_regenerate() + { + list($parser, $renderer) = $this->get_factory()->regenerate(); + + $this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser); + $this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer); + + $this->assertEquals($parser, $this->cache->get('_foo_parser'), 'The parser was not cached'); + $this->assertEquals( + array( + 'class' => get_class($renderer), + 'renderer' => serialize($renderer) + ), + $this->cache->get('_foo_renderer'), + 'The renderer was not cached' + ); + + $file = $this->get_cache_dir() . get_class($renderer) . '.php'; + $this->assertFileExists($file); + unlink($file); + } + + public function test_tidy() + { + $factory = $this->get_factory(); + + // Create a fake "old" cache file + $old_file = $this->get_cache_dir() . 's9e_foo.php'; + touch($old_file); + + // Create a current renderer + list($parser, $renderer) = $factory->regenerate(); + $new_file = $this->get_cache_dir() . get_class($renderer) . '.php'; + + // Tidy the cache + $factory->tidy(); + + $this->assertFileExists($new_file, 'The current renderer has been deleted'); + $this->assertFileNotExists($old_file, 'The old renderer has not been deleted'); + + unlink($new_file); + } + + public function test_local_url() + { + global $config, $user, $request; + + $config = array( + 'force_server_vars' => true, + 'server_protocol' => 'http://', + 'server_name' => 'path', + 'server_port' => 80, + 'script_path' => '/to', + 'cookie_secure' => false + ); + $user = new phpbb_mock_user; + $request = new phpbb_mock_request; + + $fixture = __DIR__ . '/fixtures/local_url.xml'; + $renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer'); + + $this->assertSame( + 'http://path/to/foo', + $renderer->render('[local]foo[/local]') + ); + } + + public function test_smilies_special_chars() + { + // Use a smiley that contains every special chars in every field + $fixture = __DIR__ . '/fixtures/smilies_special_chars.xml'; + $renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer'); + + $this->assertSame( + '"\'<&>', + $renderer->render('"\'<&>') + ); + } + + /** + * @testdox {INTTEXT} is supported in custom BBCodes + */ + public function test_inttext_token() + { + $fixture = __DIR__ . '/fixtures/inttext_token.xml'; + $container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $original = '[spoiler=ɎɆS]text[/spoiler]'; + $expected = '
    ɎɆS
    text
    '; + $this->assertSame($expected, $renderer->render($parser->parse($original))); + + $original = '[spoiler=N:O:P:E]text[/spoiler]'; + $expected = $original; + $this->assertSame($expected, $renderer->render($parser->parse($original))); + } +} diff --git a/tests/text_formatter/s9e/fixtures/default_formatting.xml b/tests/text_formatter/s9e/fixtures/default_formatting.xml new file mode 100644 index 0000000000..2b7236fb30 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/default_formatting.xml @@ -0,0 +1,466 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + :D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 1 + 1 + + + 2 + :-D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 2 + 1 + + + 3 + :grin: + Very Happy + icon_e_biggrin.gif + 15 + 17 + 3 + 1 + + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + + + 5 + :-) + Smile + icon_e_smile.gif + 15 + 17 + 5 + 1 + + + 6 + :smile: + Smile + icon_e_smile.gif + 15 + 17 + 6 + 1 + + + 7 + ;) + Wink + icon_e_wink.gif + 15 + 17 + 7 + 1 + + + 8 + ;-) + Wink + icon_e_wink.gif + 15 + 17 + 8 + 1 + + + 9 + :wink: + Wink + icon_e_wink.gif + 15 + 17 + 9 + 1 + + + 10 + :( + Sad + icon_e_sad.gif + 15 + 17 + 10 + 1 + + + 11 + :-( + Sad + icon_e_sad.gif + 15 + 17 + 11 + 1 + + + 12 + :sad: + Sad + icon_e_sad.gif + 15 + 17 + 12 + 1 + + + 13 + :o + Surprised + icon_e_surprised.gif + 15 + 17 + 13 + 1 + + + 14 + :-o + Surprised + icon_e_surprised.gif + 15 + 17 + 14 + 1 + + + 15 + :eek: + Surprised + icon_e_surprised.gif + 15 + 17 + 15 + 1 + + + 16 + :shock: + Shocked + icon_eek.gif + 15 + 17 + 16 + 1 + + + 17 + :? + Confused + icon_e_confused.gif + 15 + 17 + 17 + 1 + + + 18 + :-? + Confused + icon_e_confused.gif + 15 + 17 + 18 + 1 + + + 19 + :???: + Confused + icon_e_confused.gif + 15 + 17 + 19 + 1 + + + 20 + 8-) + Cool + icon_cool.gif + 15 + 17 + 20 + 1 + + + 21 + :cool: + Cool + icon_cool.gif + 15 + 17 + 21 + 1 + + + 22 + :lol: + Laughing + icon_lol.gif + 15 + 17 + 22 + 1 + + + 23 + :x + Mad + icon_mad.gif + 15 + 17 + 23 + 1 + + + 24 + :-x + Mad + icon_mad.gif + 15 + 17 + 24 + 1 + + + 25 + :mad: + Mad + icon_mad.gif + 15 + 17 + 25 + 1 + + + 26 + :P + Razz + icon_razz.gif + 15 + 17 + 26 + 1 + + + 27 + :-P + Razz + icon_razz.gif + 15 + 17 + 27 + 1 + + + 28 + :razz: + Razz + icon_razz.gif + 15 + 17 + 28 + 1 + + + 29 + :oops: + Embarrassed + icon_redface.gif + 15 + 17 + 29 + 1 + + + 30 + :cry: + Crying or Very Sad + icon_cry.gif + 15 + 17 + 30 + 1 + + + 31 + :evil: + Evil or Very Mad + icon_evil.gif + 15 + 17 + 31 + 1 + + + 32 + :twisted: + Twisted Evil + icon_twisted.gif + 15 + 17 + 32 + 1 + + + 33 + :roll: + Rolling Eyes + icon_rolleyes.gif + 15 + 17 + 33 + 1 + + + 34 + :!: + Exclamation + icon_exclaim.gif + 15 + 17 + 34 + 1 + + + 35 + :?: + Question + icon_question.gif + 15 + 17 + 35 + 1 + + + 36 + :idea: + Idea + icon_idea.gif + 15 + 17 + 36 + 1 + + + 37 + :arrow: + Arrow + icon_arrow.gif + 15 + 17 + 37 + 1 + + + 38 + :| + Neutral + icon_neutral.gif + 15 + 17 + 38 + 1 + + + 39 + :-| + Neutral + icon_neutral.gif + 15 + 17 + 39 + 1 + + + 40 + :mrgreen: + Mr. Green + icon_mrgreen.gif + 15 + 17 + 40 + 1 + + + 41 + :geek: + Geek + icon_e_geek.gif + 17 + 17 + 41 + 1 + + + 42 + :ugeek: + Uber Geek + icon_e_ugeek.gif + 17 + 18 + 42 + 1 + +
    + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + 1 + prosilver + &copy; phpBB Group + 1 + prosilver + kNg= + 0 + + +
    + + + word_id + word + replacement + + + 1 + apple + banana + +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/default_lang.xml b/tests/text_formatter/s9e/fixtures/default_lang.xml new file mode 100644 index 0000000000..2cfde4aab2 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/default_lang.xml @@ -0,0 +1,20 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + + + 13 + foo + + 1 + [foo]{TEXT}[/foo] + {L_FOO_BAR} + +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/factory.xml b/tests/text_formatter/s9e/fixtures/factory.xml new file mode 100644 index 0000000000..9ae52e9747 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/factory.xml @@ -0,0 +1,115 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + custom + + 1 + [custom]{TEXT}[/custom] + <span style="color:red">{TEXT}</span> + !\[custom\](.*?)\[/custom\]!ies + '[custom:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/custom:$uid]' + !\[custom:$uid\](.*?)\[/custom:$uid\]!s + <span style="color:red">${1}</span> + + + 14 + unsafe + + 1 + [unsafe]{TEXT}[/unsafe] + <script>{TEXT}</script> + !\[unsafe\](.*?)\[/unsafe\]!ies + '[unsafe:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/unsafe:$uid]' + !\[unsafe:$uid\](.*?)\[/unsafe:$uid\]!s + <script>${1}</script> + +
    + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + :D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 2 + 1 + + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + + + 10 + :( + Sad + icon_e_sad.gif + 15 + 17 + 10 + 1 + +
    + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + + 1 + prosilver + &copy; phpBB Group + 1 + prosilver + kNg= + 0 + + +
    + + + word_id + word + replacement + + + 1 + apple + banana + +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/inttext_token.xml b/tests/text_formatter/s9e/fixtures/inttext_token.xml new file mode 100644 index 0000000000..30b971f315 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/inttext_token.xml @@ -0,0 +1,27 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + spoiler= + + 1 + [spoiler={INTTEXT}]{TEXT}[/spoiler] +
    {INTTEXT}
    {TEXT}
    ]]>
    + + +
    ${1}
    ${2}
    ]]>
    +
    +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/local_url.xml b/tests/text_formatter/s9e/fixtures/local_url.xml new file mode 100644 index 0000000000..9db2bf4710 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/local_url.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + local + + 1 + [local]{LOCAL_URL}[/local] + {LOCAL_URL}]]> + + bbcode_specialchars('${1}').'[/local:$uid]']]> + + http://path/to/phpBB/${1}]]> + +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml new file mode 100644 index 0000000000..d3a7cfa4f7 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml @@ -0,0 +1,23 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + "'<&> + "'<&> + "'<&>.png + 15 + 17 + 2 + 1 + +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/style_inheritance.xml b/tests/text_formatter/s9e/fixtures/style_inheritance.xml new file mode 100644 index 0000000000..a692d0ef2d --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/style_inheritance.xml @@ -0,0 +1,66 @@ + + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + + 1 + foo + + 1 + foo + + QA== + 0 + + + + 2 + fooplus + + 1 + fooplus + QA== + 1 + + + + 3 + fooplusplus + + 1 + fooplusplus + QA== + 2 + + + + 4 + bar + + 1 + bar + + QA== + 0 + + + + 5 + barplus + + 1 + barplus + QA== + 4 + + +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/styles.xml b/tests/text_formatter/s9e/fixtures/styles.xml new file mode 100644 index 0000000000..8004412aea --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles.xml @@ -0,0 +1,36 @@ + + + + style_id + style_name + style_copyright + style_active + style_path + bbcode_bitfield + style_parent_id + style_parent_tree + + + 1 + foo + + 1 + foo + + QA== + 0 + + + + 2 + bar + + 1 + bar + + QA== + 0 + + +
    +
    diff --git a/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html new file mode 100644 index 0000000000..a17446581a --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html @@ -0,0 +1,40 @@ +
      +
        +
      + +
        +
      + +
    • +
    • + +
      {USERNAME} {L_WROTE}{L_COLON} +
      +
      + +

      {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

      +
      + +
      +
      + + + + + + + + + + +{TEXT} + +{TEXT} + +{L_IMAGE} + +{DESCRIPTION} + +{DESCRIPTION} + + diff --git a/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html new file mode 100644 index 0000000000..cd2f0acae3 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html @@ -0,0 +1,40 @@ +
        +
          +
        + +
          +
        + +
      • +
      • + +
        {USERNAME} {L_WROTE}{L_COLON} +
        +
        + +

        {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

        +
        + +
        +
        + + + + + + + + + + +{TEXT} + +{TEXT} + +{L_IMAGE} + +{DESCRIPTION} + +{DESCRIPTION} + + diff --git a/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html new file mode 100644 index 0000000000..909c09df5a --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html @@ -0,0 +1,40 @@ +
          +
            +
          + +
            +
          + +
        • +
        • + +
          {USERNAME} {L_WROTE}{L_COLON} +
          +
          + +

          {L_CODE}{L_COLON} {L_SELECT_ALL_CODE}

          +
          + +
          +
          + + + + + + + + + + +{TEXT} + +{TEXT} + +{L_IMAGE} + +{DESCRIPTION} + +{DESCRIPTION} + + diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php new file mode 100644 index 0000000000..528305a11c --- /dev/null +++ b/tests/text_formatter/s9e/parser_test.php @@ -0,0 +1,162 @@ +getMockBuilder('s9e\\TextFormatter\\Parser') + ->disableOriginalConstructor() + ->getMock(); + + $cache = $this->getMock('phpbb_mock_cache'); + $cache->expects($this->once()) + ->method('get') + ->with('_foo_parser') + ->will($this->returnValue($mock)); + + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + new phpbb_mock_container_builder + ); + } + + public function test_use_from_cache() + { + $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') + ->disableOriginalConstructor() + ->getMock(); + + $mock->expects($this->once()) + ->method('parse') + ->with('test') + ->will($this->returnValue('test')); + + $cache = new phpbb_mock_cache; + $cache->put('_foo_parser', $mock); + + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + new phpbb_mock_container_builder + ); + + $this->assertSame('test', $parser->parse('test')); + } + + public function test_regenerate_on_cache_miss() + { + $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') + ->disableOriginalConstructor() + ->getMock(); + + $mock->expects($this->once()) + ->method('parse') + ->with('test') + ->will($this->returnValue('test')); + + $factory = $this->getMock('stdClass', array('regenerate')); + $factory->expects($this->once()) + ->method('regenerate') + ->will($this->returnValue(array($mock, false))); + + $container = new phpbb_mock_container_builder; + $container->set('text_formatter.s9e.factory', $factory); + + $parser = new \phpbb\textformatter\s9e\parser( + new phpbb_mock_cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + $container + ); + + $this->assertSame('test', $parser->parse('test')); + } + + /** + * @dataProvider get_options_tests() + */ + public function test_options($adapter_method, $adapter_arg, $concrete_method, $concrete_arg) + { + $mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') + ->setMethods(array($concrete_method)) + ->disableOriginalConstructor() + ->getMock(); + foreach ((array) $concrete_arg as $i => $concrete_arg) + { + $mock->expects($this->at($i)) + ->method($concrete_method) + ->with($concrete_arg); + } + + $cache = new phpbb_mock_cache; + $cache->put('_foo_parser', $mock); + + $parser = new \phpbb\textformatter\s9e\parser( + $cache, + '_foo_parser', + $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(), + new phpbb_mock_container_builder + ); + + call_user_func_array(array($parser, $adapter_method), (array) $adapter_arg); + } + + public function get_options_tests() + { + return array( + array( + 'disable_bbcode', 'url', + 'disableTag', 'URL' + ), + array( + 'disable_bbcodes', null, + 'disablePlugin', 'BBCodes' + ), + array( + 'disable_censor', null, + 'disablePlugin', 'Censor' + ), + array( + 'disable_magic_url', null, + 'disablePlugin', array('Autoemail', 'Autolink') + ), + array( + 'disable_smilies', null, + 'disablePlugin', 'Emoticons' + ), + array( + 'enable_bbcode', 'url', + 'enableTag', 'URL' + ), + array( + 'enable_bbcodes', null, + 'enablePlugin', 'BBCodes' + ), + array( + 'enable_censor', null, + 'enablePlugin', 'Censor' + ), + array( + 'enable_magic_url', null, + 'enablePlugin', array('Autoemail', 'Autolink') + ), + array( + 'enable_smilies', null, + 'enablePlugin', 'Emoticons' + ) + ); + } +} diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php new file mode 100644 index 0000000000..76babbfdf3 --- /dev/null +++ b/tests/text_formatter/s9e/renderer_test.php @@ -0,0 +1,355 @@ +get_cache_dir() . 'renderer_foo.php', + 'getMockForAbstractClass('s9e\\TextFormatter\\Renderer'); + + $cache = $this->getMock('phpbb_mock_cache'); + $cache->expects($this->once()) + ->method('get') + ->with('_foo_renderer') + ->will($this->returnValue(array('class' => 'renderer_foo', 'renderer' => serialize($mock)))); + + $container = new phpbb_mock_container_builder; + $container->set('text_formatter.s9e.factory', $factory); + + $renderer = new \phpbb\textformatter\s9e\renderer( + $cache, + $this->get_cache_dir(), + '_foo_renderer', + $container + ); + } + + public function test_regenerate_on_cache_miss() + { + $mock = $this->getMockForAbstractClass('s9e\\TextFormatter\\Renderer'); + + $cache = $this->getMock('phpbb_mock_cache'); + $cache->expects($this->once()) + ->method('get') + ->with('_foo_renderer') + ->will($this->returnValue(false)); + + $factory = $this->getMock('stdClass', array('regenerate')); + $factory->expects($this->once()) + ->method('regenerate') + ->will($this->returnValue(array($mock, false))); + + $container = new phpbb_mock_container_builder; + $container->set('text_formatter.s9e.factory', $factory); + + $renderer = new \phpbb\textformatter\s9e\renderer( + $cache, + $this->get_cache_dir(), + '_foo_renderer', + $container + ); + } + + /** + * @dataProvider get_options_cases + */ + public function test_options($original, $expected, $calls) + { + $container = new phpbb_mock_container_builder; + $this->get_test_case_helpers()->set_s9e_services($container); + + $renderer = $container->get('text_formatter.renderer'); + + foreach ($calls as $method => $arg) + { + $renderer->$method($arg); + } + + $this->assertSame($expected, $renderer->render($original)); + } + + public function get_options_cases() + { + return array( + array( + 'apple', + 'banana', + array('set_viewcensors' => true) + ), + array( + 'apple', + 'apple', + array('set_viewcensors' => false) + ), + array( + '[flash=123,456]http://example.org/foo.swf[/flash]', + '', + array('set_viewflash' => true) + ), + array( + '[img]http://example.org/foo.png[/img]', + 'Image', + array('set_viewimg' => true) + ), + array( + ':)', + ':)', + array('set_viewsmilies' => true) + ), + array( + ':)', + ':)', + array('set_viewsmilies' => false) + ), + ); + } + + /** + * @dataProvider get_default_options_cases + */ + public function test_default_options($original, $expected, $setup = null) + { + $container = new phpbb_mock_container_builder; + + if (isset($setup)) + { + $setup($container, $this); + } + + $this->get_test_case_helpers()->set_s9e_services($container); + + $this->assertSame($expected, $container->get('text_formatter.renderer')->render($original)); + } + + public function get_default_options_cases() + { + return array( + array( + 'apple', + 'banana' + ), + array( + 'apple', + 'banana', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', false); + + $phpbb_container->set('user', $user); + } + ), + array( + 'apple', + 'banana', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', false); + + $config = new \phpbb\config\config(array('allow_nocensors' => true)); + + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + } + ), + array( + 'apple', + 'apple', + function ($phpbb_container, $test) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', false); + + $config = new \phpbb\config\config(array('allow_nocensors' => true)); + + $auth = $test->getMock('phpbb\\auth\\auth'); + $auth->expects($test->any()) + ->method('acl_get') + ->with('u_chgcensors') + ->will($test->returnValue(true)); + + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + $phpbb_container->set('auth', $auth); + } + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + '' + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + 'http://localhost/foo.swf', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewflash', false); + + $phpbb_container->set('user', $user); + } + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'Image' + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'http://localhost/mrgreen.gif', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewimg', false); + + $phpbb_container->set('user', $user); + } + ), + array( + ':)', + ':)' + ), + array( + ':)', + ':)', + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('smilies', false); + + $phpbb_container->set('user', $user); + } + ), + ); + } + + public function test_default_lang() + { + global $phpbb_container; + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/default_lang.xml'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + + $this->assertSame('FOO_BAR', $renderer->render('')); + } + + /** + * @dataProvider get_option_names + */ + public function test_get_option($option_name) + { + global $phpbb_container; + $this->get_test_case_helpers()->set_s9e_services(); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + + $renderer->{'set_' . $option_name}(false); + $this->assertFalse($renderer->{'get_' . $option_name}()); + $renderer->{'set_' . $option_name}(true); + $this->assertTrue($renderer->{'get_' . $option_name}()); + } + + public function get_option_names() + { + return array( + array('viewcensors'), + array('viewflash'), + array('viewimg'), + array('viewsmilies') + ); + } + + public function test_styles() + { + global $phpbb_container; + + $tests = array( + 1 => 'bold', + 2 => 'bold' + ); + + foreach ($tests as $style_id => $expected) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->style = array('style_id' => $style_id); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/styles.xml', __DIR__ . '/fixtures/styles/'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + $this->assertSame( + $expected, + $renderer->render('[b]bold[/b]') + ); + } + } + + public function test_style_inheritance1() + { + global $phpbb_container; + + // Style 3 inherits from 2 which inherits from 1. Only style 1 has a bbcode.html + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->style = array('style_id' => 3); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + $this->assertSame( + 'bold', + $renderer->render('[b]bold[/b]') + ); + } + + public function test_style_inheritance2() + { + global $phpbb_container; + + // Style 5 inherits from 4, but both have a bbcode.html + $tests = array( + 4 => 'bold', + 5 => 'bold' + ); + + foreach ($tests as $style_id => $expected) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->style = array('style_id' => $style_id); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/'); + + $renderer = $phpbb_container->get('text_formatter.renderer'); + $this->assertSame( + $expected, + $renderer->render('[b]bold[/b]') + ); + } + } +} diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php new file mode 100644 index 0000000000..510beba817 --- /dev/null +++ b/tests/text_formatter/s9e/utils_test.php @@ -0,0 +1,157 @@ +get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->unparse($original)); + } + + public function get_unparse_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + "Multi
          \nline
          ", + "Multi\nline" + ), + array( + '[b]bold[/b]', + '[b]bold[/b]' + ) + ); + } + + /** + * @dataProvider get_remove_formatting_tests + */ + public function test_remove_formatting($original, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->remove_formatting($original)); + } + + public function get_remove_formatting_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + "Multi
          \nline
          ", + "Multi\nline" + ), + array( + '[b]bold[/b]', + 'bold' + ) + ); + } + + /** + * @dataProvider get_clean_formatting_tests + */ + public function test_clean_formatting($original, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->clean_formatting($original)); + } + + public function get_clean_formatting_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + "Multi
          \nline
          ", + "Multi\nline" + ), + array( + '[b]bold[/b]', + ' bold ' + ) + ); + } + + /** + * @dataProvider get_remove_bbcode_tests + */ + public function test_remove_bbcode($original, $name, $depth, $expected) + { + $container = $this->get_test_case_helpers()->set_s9e_services(); + $utils = $container->get('text_formatter.utils'); + + $this->assertSame($expected, $utils->remove_bbcode($original, $name, $depth)); + } + + public function get_remove_bbcode_tests() + { + return array( + array( + 'Plain text', + 'b', + 1, + 'Plain text' + ), + array( + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] +q1[/quote] +q0[/quote] +[b]bold[/b]', + 'quote', + 0, + ' +[b]bold[/b]' + ), + array( + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] +q1[/quote] +q0[/quote] +[b]bold[/b]', + 'quote', + 1, + '[quote="u0"] +q0[/quote] +[b]bold[/b]' + ), + array( + '[quote="u0"][quote="u1"][quote="u2"]q2[/quote] +q1[/quote] +q0[/quote] +[b]bold[/b]', + 'quote', + 2, + '[quote="u0"][quote="u1"] +q1[/quote] +q0[/quote] +[b]bold[/b]' + ), + ); + } +} diff --git a/tests/text_processing/decode_message_test.php b/tests/text_processing/decode_message_test.php new file mode 100644 index 0000000000..855b3c6c57 --- /dev/null +++ b/tests/text_processing/decode_message_test.php @@ -0,0 +1,87 @@ +assertSame($expected, $actual); + } + + public function get_legacy_tests() + { + return array( + array( + "&<>"'", + "&<>"'" + ), + array( + ':)', + ':)' + ), + /** + * Fails as per PHPBB3-8420 + * @link http://tracker.phpbb.com/browse/PHPBB3-8420 + * + array( + '[url=http://example.com:2cpxwbdy]:arrow: here[/url:2cpxwbdy]', + '[url=http://example.com] :arrow: here[/url]', + '2cpxwbdy' + ), + */ + ); + } + + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected) + { + $this->get_test_case_helpers()->set_s9e_services(); + + $actual = $original; + decode_message($actual); + + $this->assertSame($expected, $actual); + } + + public function get_text_formatter_tests() + { + return array( + array( + "&<>\"'", + "&<>"'" + ), + array( + ':)', + ':)' + ), + array( + "a
          \nb
          ", + "a\nb" + ), + /** + * @link http://tracker.phpbb.com/browse/PHPBB3-8420 + */ + array( + '[url=http://example.com] :arrow: here[/url]', + '[url=http://example.com] :arrow: here[/url]' + ), + ); + } +} diff --git a/tests/text_processing/fixtures/empty.xml b/tests/text_processing/fixtures/empty.xml new file mode 100644 index 0000000000..d8206ad124 --- /dev/null +++ b/tests/text_processing/fixtures/empty.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/text_processing/fixtures/smilies.xml b/tests/text_processing/fixtures/smilies.xml new file mode 100644 index 0000000000..25b2e60836 --- /dev/null +++ b/tests/text_processing/fixtures/smilies.xml @@ -0,0 +1,443 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 1 + :D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 1 + 1 + + + 2 + :-D + Very Happy + icon_e_biggrin.gif + 15 + 17 + 2 + 1 + + + 3 + :grin: + Very Happy + icon_e_biggrin.gif + 15 + 17 + 3 + 1 + + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + + + 5 + :-) + Smile + icon_e_smile.gif + 15 + 17 + 5 + 1 + + + 6 + :smile: + Smile + icon_e_smile.gif + 15 + 17 + 6 + 1 + + + 7 + ;) + Wink + icon_e_wink.gif + 15 + 17 + 7 + 1 + + + 8 + ;-) + Wink + icon_e_wink.gif + 15 + 17 + 8 + 1 + + + 9 + :wink: + Wink + icon_e_wink.gif + 15 + 17 + 9 + 1 + + + 10 + :( + Sad + icon_e_sad.gif + 15 + 17 + 10 + 1 + + + 11 + :-( + Sad + icon_e_sad.gif + 15 + 17 + 11 + 1 + + + 12 + :sad: + Sad + icon_e_sad.gif + 15 + 17 + 12 + 1 + + + 13 + :o + Surprised + icon_e_surprised.gif + 15 + 17 + 13 + 1 + + + 14 + :-o + Surprised + icon_e_surprised.gif + 15 + 17 + 14 + 1 + + + 15 + :eek: + Surprised + icon_e_surprised.gif + 15 + 17 + 15 + 1 + + + 16 + :shock: + Shocked + icon_eek.gif + 15 + 17 + 16 + 1 + + + 17 + :? + Confused + icon_e_confused.gif + 15 + 17 + 17 + 1 + + + 18 + :-? + Confused + icon_e_confused.gif + 15 + 17 + 18 + 1 + + + 19 + :???: + Confused + icon_e_confused.gif + 15 + 17 + 19 + 1 + + + 20 + 8-) + Cool + icon_cool.gif + 15 + 17 + 20 + 1 + + + 21 + :cool: + Cool + icon_cool.gif + 15 + 17 + 21 + 1 + + + 22 + :lol: + Laughing + icon_lol.gif + 15 + 17 + 22 + 1 + + + 23 + :x + Mad + icon_mad.gif + 15 + 17 + 23 + 1 + + + 24 + :-x + Mad + icon_mad.gif + 15 + 17 + 24 + 1 + + + 25 + :mad: + Mad + icon_mad.gif + 15 + 17 + 25 + 1 + + + 26 + :P + Razz + icon_razz.gif + 15 + 17 + 26 + 1 + + + 27 + :-P + Razz + icon_razz.gif + 15 + 17 + 27 + 1 + + + 28 + :razz: + Razz + icon_razz.gif + 15 + 17 + 28 + 1 + + + 29 + :oops: + Embarrassed + icon_redface.gif + 15 + 17 + 29 + 1 + + + 30 + :cry: + Crying or Very Sad + icon_cry.gif + 15 + 17 + 30 + 1 + + + 31 + :evil: + Evil or Very Mad + icon_evil.gif + 15 + 17 + 31 + 1 + + + 32 + :twisted: + Twisted Evil + icon_twisted.gif + 15 + 17 + 32 + 1 + + + 33 + :roll: + Rolling Eyes + icon_rolleyes.gif + 15 + 17 + 33 + 1 + + + 34 + :!: + Exclamation + icon_exclaim.gif + 15 + 17 + 34 + 1 + + + 35 + :?: + Question + icon_question.gif + 15 + 17 + 35 + 1 + + + 36 + :idea: + Idea + icon_idea.gif + 15 + 17 + 36 + 1 + + + 37 + :arrow: + Arrow + icon_arrow.gif + 15 + 17 + 37 + 1 + + + 38 + :| + Neutral + icon_neutral.gif + 15 + 17 + 38 + 1 + + + 39 + :-| + Neutral + icon_neutral.gif + 15 + 17 + 39 + 1 + + + 40 + :mrgreen: + Mr. Green + icon_mrgreen.gif + 15 + 17 + 40 + 1 + + + 41 + :geek: + Geek + icon_e_geek.gif + 17 + 17 + 41 + 1 + + + 42 + :ugeek: + Uber Geek + icon_e_ugeek.gif + 17 + 18 + 42 + 1 + + + 43 + 8) + 8) + custom.gif + 17 + 18 + 42 + 1 + +
          +
          diff --git a/tests/text_processing/generate_text_for_display_test.php b/tests/text_processing/generate_text_for_display_test.php index 057416da33..fe83938c0b 100644 --- a/tests/text_processing/generate_text_for_display_test.php +++ b/tests/text_processing/generate_text_for_display_test.php @@ -11,10 +11,8 @@ * */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../mock/user.php'; -require_once dirname(__FILE__) . '/../mock/cache.php'; +require_once __DIR__ . '/../../phpBB/includes/functions.php'; +require_once __DIR__ . '/../../phpBB/includes/functions_content.php'; class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_case { @@ -24,21 +22,175 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca parent::setUp(); - $cache = new phpbb_mock_cache; + $phpbb_dispatcher = new phpbb_mock_event_dispatcher; + $config = new \phpbb\config\config(array()); + set_config(null, null, null, $config); + } - $user = new phpbb_mock_user; + /** + * @dataProvider get_legacy_tests + */ + public function test_legacy($original, $expected, $uid = '', $bitfield = '', $flags = 0, $censor_text = true) + { + global $cache, $user; + + $cache = new phpbb_mock_cache; + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewcensors', true); + $user->optionset('viewflash', true); + $user->optionset('viewimg', true); + $user->optionset('viewsmilies', true); + + $actual = generate_text_for_display($original, $uid, $bitfield, $flags, $censor_text); + + $this->assertSame($expected, $actual); + } + + public function get_legacy_tests() + { + return array( + array( + '', + '' + ), + array( + '0', + '0' + ), + ); + } + + public function test_censor_is_restored() + { + global $phpbb_container; + + $phpbb_container = new phpbb_mock_container_builder; + + $user = new \phpbb\user('\\phpbb\\datetime'); $user->optionset('viewcensors', false); - $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + $config = new \phpbb\config\config(array('allow_nocensors' => true)); + + $auth = $this->getMock('phpbb\\auth\\auth'); + $auth->expects($this->any()) + ->method('acl_get') + ->with('u_chgcensors') + ->will($this->returnValue(true)); + + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + $phpbb_container->set('auth', $auth); + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + $renderer = $phpbb_container->get('text_formatter.renderer'); + + $original = 'apple'; + + $renderer->set_viewcensors(false); + $this->assertSame('apple', $renderer->render($original)); + $renderer->set_viewcensors(true); + $this->assertSame('banana', $renderer->render($original)); + $this->assertSame('apple', generate_text_for_display($original, '', '', 0, false)); + $this->assertSame('banana', $renderer->render($original), 'The original setting was not restored'); + + $renderer->set_viewcensors(false); + $this->assertSame('apple', $renderer->render($original)); + $this->assertSame('banana', generate_text_for_display($original, '', '', 0, truee)); + $this->assertSame('apple', $renderer->render($original), 'The original setting was not restored'); } - public function test_empty_string() + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected, $censor_text = true, $setup = null) { - $this->assertSame('', generate_text_for_display('', '', '', 0)); + global $phpbb_container; + + $phpbb_container = new phpbb_mock_container_builder; + + if (isset($setup)) + { + $setup($phpbb_container, $this); + } + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + + $this->assertSame($expected, generate_text_for_display($original, '', '', 0, $censor_text)); } - public function test_zero_string() + public function get_text_formatter_tests() { - $this->assertSame('0', generate_text_for_display('0', '', '', 0)); + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + 'Hello [url=http://example.org]world[/url]', + 'Hello world' + ), + array( + '&<>"\'', + '&<>"\'' + ), + array( + 'apple', + 'banana', + true + ), + array( + 'apple', + 'apple', + false + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + '' + ), + array( + '[flash=123,456]http://localhost/foo.swf[/flash]', + 'http://localhost/foo.swf', + true, + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewflash', false); + + $phpbb_container->set('user', $user); + } + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'Image' + ), + array( + '[img]http://localhost/mrgreen.gif[/img]', + 'http://localhost/mrgreen.gif', + true, + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('viewimg', false); + + $phpbb_container->set('user', $user); + } + ), + array( + ':)', + ':)' + ), + array( + ':)', + ':)', + true, + function ($phpbb_container) + { + $user = new \phpbb\user('\\phpbb\\datetime'); + $user->optionset('smilies', false); + + $phpbb_container->set('user', $user); + } + ), + ); } } diff --git a/tests/text_processing/generate_text_for_edit_test.php b/tests/text_processing/generate_text_for_edit_test.php new file mode 100644 index 0000000000..85b3a6a0ab --- /dev/null +++ b/tests/text_processing/generate_text_for_edit_test.php @@ -0,0 +1,90 @@ +optionset('viewcensors', false); + + $return = generate_text_for_edit($original, $uid, $flags); + + $this->assertSame($expected, $return['text']); + } + + public function get_legacy_tests() + { + return array( + array( + '', + '' + ), + array( + '0', + '0' + ), + array( + 'Hello [url=http://example.org:1f4coh9x]world[/url:1f4coh9x] :)', + 'Hello [url=http://example.org]world[/url] :)', + '1f4coh9x', + 0 + ), + array( + "&<>"'", + "&<>"'" + ) + ); + } + + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected) + { + global $phpbb_dispatcher; + $phpbb_dispatcher = new phpbb_mock_event_dispatcher; + $this->get_test_case_helpers()->set_s9e_services(); + + $return = generate_text_for_edit($original, '', 0); + + $this->assertSame($expected, $return['text']); + } + + public function get_text_formatter_tests() + { + return array( + array( + 'Plain text', + 'Plain text' + ), + array( + 'Hello [url=http://example.org]world[/url] :)', + 'Hello [url=http://example.org]world[/url] :)' + ), + array( + '&<>"\'', + "&<>"'" + ) + ); + } +} diff --git a/tests/text_processing/generate_text_for_storage_test.php b/tests/text_processing/generate_text_for_storage_test.php new file mode 100644 index 0000000000..0bacaacfb8 --- /dev/null +++ b/tests/text_processing/generate_text_for_storage_test.php @@ -0,0 +1,70 @@ +set('config', $config); + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + + $phpbb_dispatcher = new phpbb_mock_event_dispatcher; + } + + /** + * @dataProvider get_text_formatter_tests + */ + public function test_text_formatter($original, $expected, $allow_bbcode = true, $allow_urls = true, $allow_smilies = true, $setup = null) + { + $actual = $original; + $uid = ''; + $bitfield = ''; + $flags = 0; + + if (isset($setup)) + { + $setup(); + } + + generate_text_for_storage($actual, $uid, $bitfield, $flags, $allow_bbcode, $allow_urls, $allow_smilies); + + $this->assertSame($expected, $actual); + } + + public function get_text_formatter_tests() + { + return array( + array( + 'Hello world', + 'Hello world' + ), + array( + 'Hello [url=http://example.org]world[/url] :)', + 'Hello [url=http://example.org]world[/url] :)' + ), + array( + '&<>"\'', + '&<>"\'' + ), + ); + } +} diff --git a/tests/text_processing/message_parser_test.php b/tests/text_processing/message_parser_test.php new file mode 100644 index 0000000000..59af2553f8 --- /dev/null +++ b/tests/text_processing/message_parser_test.php @@ -0,0 +1,532 @@ + 999)); + + $map = array( + array('MAX_FLASH_HEIGHT_EXCEEDED', 123, 'Your flash files may only be up to 123 pixels high.'), + array('MAX_FLASH_WIDTH_EXCEEDED', 456, 'Your flash files may only be up to 456 pixels wide.'), + array('MAX_FONT_SIZE_EXCEEDED', 120, 'You may only use fonts up to size 120.'), + array('MAX_FONT_SIZE_EXCEEDED', 200, 'You may only use fonts up to size 200.'), + array('MAX_IMG_HEIGHT_EXCEEDED', 12, 'Your images may only be up to 12 pixels high.'), + array('MAX_IMG_WIDTH_EXCEEDED', 34, 'Your images may only be up to 34 pixels wide.'), + array('TOO_MANY_SMILIES', 3, 'Your message contains too many smilies. The maximum number of smilies allowed is 3.'), + array('TOO_MANY_URLS', 2, 'Your message contains too many URLs. The maximum number of URLs allowed is 2.'), + array('UNAUTHORISED_BBCODE', '[flash]', 'You cannot use certain BBCodes: [flash].'), + array('UNAUTHORISED_BBCODE', '[img]', 'You cannot use certain BBCodes: [img].'), + array('UNAUTHORISED_BBCODE', '[quote]', 'You cannot use certain BBCodes: [quote].'), + array('UNAUTHORISED_BBCODE', '[url]', 'You cannot use certain BBCodes: [url].'), + ); + + $user = $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(); + $user->expects($this->any()) + ->method('lang') + ->will($this->returnValueMap($map)); + + $user->lang = array( + 'NO_POLL_TITLE' => 'You have to enter a poll title.', + 'POLL_TITLE_TOO_LONG' => 'The poll title must contain fewer than 100 characters.', + 'POLL_TITLE_COMP_TOO_LONG' => 'The parsed size of your poll title is too large, consider removing BBCodes or smilies.', + 'TOO_FEW_POLL_OPTIONS' => 'You must enter at least two poll options.', + 'TOO_MANY_POLL_OPTIONS' => 'You have tried to enter too many poll options.', + 'TOO_MANY_USER_OPTIONS' => 'You cannot specify more options per user than existing poll options.', + 'UNABLE_GET_IMAGE_SIZE' => 'It was not possible to determine the dimensions of the image.' + ); + + $phpbb_container = new phpbb_mock_container_builder; + $phpbb_container->set('user', $user); + $phpbb_container->set('config', $config); + + if (isset($setup)) + { + $setup($parser, $phpbb_container, $this); + } + + $this->get_test_case_helpers()->set_s9e_services($phpbb_container); + } + + /** + * @dataProvider get_test_polls + */ + public function test_parse_poll($poll, $expected, $warn_msg = array()) + { + $this->prepare_s9e_services(); + + $message_parser = new parse_message('Me[i]s[/i]sage'); + + // Add some default values + $poll += array( + 'poll_length' => 123, + 'poll_start' => 123, + 'poll_last_vote' => 123, + 'poll_vote_change' => true, + 'enable_bbcode' => true, + 'enable_urls' => true, + 'enable_smilies' => true, + 'img_status' => true + ); + + $message_parser->parse_poll($poll); + $this->assertSame($expected, array_intersect_key($poll, $expected)); + + $this->assertSame( + 'Me[i]s[/i]sage', + $message_parser->parse(true, true, true, true, true, true, true, false) + ); + + $this->assertSame($warn_msg, $message_parser->warn_msg); + } + + public function get_test_polls() + { + return array( + array( + array( + 'poll_title' => 'foo [b]bar[/b] baz', + 'poll_option_text' => "[i]foo[/i]\nbar\n[i]baz[/i]", + 'poll_max_options' => 3, + 'poll_options_size' => 3 + ), + array( + 'poll_title' => 'foo [b]bar[/b] baz', + 'poll_option_text' => "[i]foo[/i]\nbar\n[i]baz[/i]", + 'poll_options' => array( + '[i]foo[/i]', + 'bar', + '[i]baz[/i]' + ) + ) + ), + array( + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[quote]quote[/quote]\n:)", + 'poll_max_options' => 2, + 'poll_options_size' => 2 + ), + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[quote]quote[/quote]\n:)", + 'poll_options' => array( + '[quote]quote[/quote]', + ':)' + ) + ), + array('You cannot use certain BBCodes: [quote].') + ), + array( + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[flash=12,34]http://example.org/x.swf[/flash]\n:)", + 'poll_max_options' => 2, + 'poll_options_size' => 2 + ), + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[flash=12,34]http://example.org/x.swf[/flash]\n:)", + 'poll_options' => array( + '[flash=12,34]http://example.org/x.swf[/flash]', + ':)' + ) + ), + array('You cannot use certain BBCodes: [flash].') + ), + array( + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[b]x\ny[/b]", + 'poll_max_options' => 2, + 'poll_options_size' => 2 + ), + array( + 'poll_title' => 'xxx', + 'poll_option_text' => "[b]x\ny[/b]", + 'poll_options' => array( + '[b]x', + 'y[/b]', + ) + ) + ), + ); + } + + /** + * @dataProvider get_test_cases + */ + public function test_options($original, $expected, array $args, $setup = null, $warn_msg = array()) + { + $this->prepare_s9e_services($setup); + + $message_parser = new parse_message($original); + call_user_func_array(array($message_parser, 'parse'), $args); + + $this->assertSame($expected, $message_parser->message); + $this->assertSame($warn_msg, $message_parser->warn_msg); + } + + public function get_test_cases() + { + return array( + array( + '[b]bold[/b]', + '[b]bold[/b]', + array(true, true, true, true, true, true, true) + ), + array( + '[b]bold[/b]', + '[b]bold[/b]', + array(false, true, true, true, true, true, true) + ), + array( + 'http://example.org', + 'http://example.org', + array(true, true, true, true, true, true, true) + ), + array( + 'http://example.org', + 'http://example.org', + array(true, false, true, true, true, true, true) + ), + array( + ':)', + ':)', + array(true, true, true, true, true, true, true) + ), + array( + ':)', + ':)', + array(true, true, false, true, true, true, true) + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, true, true, true, true) + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, false, true, true, true), + null, + array('You cannot use certain BBCodes: [img].') + ), + array( + '[flash=12,34]http://example.org/foo.swf[/flash]', + '[flash=12,34]http://example.org/foo.swf[/flash]', + array(true, true, true, true, true, true, true) + ), + array( + '[flash=12,34]http://example.org/foo.swf[/flash]', + '[flash=12,34]http://example.org/foo.swf[/flash]', + array(true, true, true, true, false, true, true), + null, + array('You cannot use certain BBCodes: [flash].') + ), + array( + '[quote="foo"]bar :)[/quote]', + '[quote="foo"]bar :)[/quote]', + array(true, true, true, true, true, true, true) + ), + array( + '[quote="foo"]bar :)[/quote]', + '[quote="foo"]bar :)[/quote]', + array(true, true, true, true, true, false, true), + null, + array('You cannot use certain BBCodes: [quote].') + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, true, true, true, true) + ), + array( + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + '[url=http://example.org][img]http://example.org/img.png[/img][/url]', + array(true, true, true, true, true, true, false), + null, + array('You cannot use certain BBCodes: [url].') + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 200); + } + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 0); + } + ), + array( + '[size=2000]2000[/size]', + '[size=2000]2000[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 200); + }, + array('You may only use fonts up to size 200.') + ), + array( + '[size=0]0[/size]', + '[size=0]0[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_font_size', 200); + } + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_font_size', 200); + } + ), + array( + '[size=200]200[/size]', + '[size=200]200[/size]', + array(true, true, true, true, true, true, true, true, 'sig'), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_font_size', 120); + }, + array('You may only use fonts up to size 120.') + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 12); + }, + array('Your images may only be up to 12 pixels high.') + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_width', 34); + }, + array('Your images may only be up to 34 pixels wide.') + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 0); + $phpbb_container->get('config')->set('max_post_img_width', 0); + } + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 100); + $phpbb_container->get('config')->set('max_post_img_width', 100); + } + ), + array( + '[img]http://example.org/100x100.png[/img]', + '[img]http://example.org/100x100.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_img_height', 12); + $phpbb_container->get('config')->set('max_sig_img_width', 34); + } + ), + array( + '[img]http://example.org/404.png[/img]', + '[img]http://example.org/404.png[/img]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 12); + }, + array('It was not possible to determine the dimensions of the image.') + ), + array( + '[flash=999,999]http://example.org/foo.swf[/flash]', + '[flash=999,999]http://example.org/foo.swf[/flash]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_height', 123); + }, + array('Your flash files may only be up to 123 pixels high.') + ), + array( + '[flash=999,999]http://example.org/foo.swf[/flash]', + '[flash=999,999]http://example.org/foo.swf[/flash]', + array(true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_img_width', 456); + }, + array('Your flash files may only be up to 456 pixels wide.') + ), + array( + ':) :) :)', + ':) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_smilies', 3); + } + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_smilies', 3); + }, + array('Your message contains too many smilies. The maximum number of smilies allowed is 3.') + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_smilies', 0); + } + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_smilies', 3); + } + ), + array( + ':) :) :) :)', + ':) :) :) :)', + array(true, true, true, true, true, true, true, true, 'sig'), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_smilies', 3); + }, + array('Your message contains too many smilies. The maximum number of smilies allowed is 3.') + ), + array( + 'http://example.org http://example.org http://example.org', + 'http://example.org http://example.org http://example.org', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_urls', 2); + }, + array('Your message contains too many URLs. The maximum number of URLs allowed is 2.') + ), + array( + 'http://example.org http://example.org http://example.org', + 'http://example.org http://example.org http://example.org', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_post_urls', 0); + } + ), + array( + 'http://example.org http://example.org http://example.org', + 'http://example.org http://example.org http://example.org', + array(true, true, true, true, true, true, true, true), + function ($parser, $phpbb_container) + { + $phpbb_container->get('config')->set('max_sig_urls', 2); + } + ), + ); + } +} + +class phpbb_text_processing_message_parser_test_proxy +{ + protected $response; + + public function stream_open($url) + { + if (strpos($url, '100x100')) + { + // Return a 100 x 100 PNG image + $this->response = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAGQAAABkAQAAAABYmaj5AAAAE0lEQVR4AWOgKxgFo2AUjIJRAAAFeAABHs0ozQAAAABJRU5ErkJggg=='); + } + else + { + $this->response = '404 not found'; + } + + return true; + } + + public function stream_stat() + { + return false; + } + + public function stream_read($len) + { + $chunk = substr($this->response, 0, $len); + $this->response = substr($this->response, $len); + + return $chunk; + } + + public function stream_eof() + { + return ($this->response === false); + } +} diff --git a/tests/text_processing/smilies_test.php b/tests/text_processing/smilies_test.php new file mode 100644 index 0000000000..cd35c25525 --- /dev/null +++ b/tests/text_processing/smilies_test.php @@ -0,0 +1,48 @@ +get_test_case_helpers()->set_s9e_services(null, __DIR__ . '/fixtures/smilies.xml'); + $parser = $container->get('text_formatter.parser'); + $renderer = $container->get('text_formatter.renderer'); + + $this->assertSame($expected, $renderer->render($parser->parse($original))); + } + + public function get_text_formatter_tests() + { + return array( + array( + ':) beginning', + ':) beginning' + ), + array( + 'end :)', + 'end :)' + ), + array( + ':)', + ':)' + ), + array( + 'xx (18) 8) xx', + 'xx (18) 8) xx' + ), + ); + } +} diff --git a/tests/text_processing/strip_bbcode_test.php b/tests/text_processing/strip_bbcode_test.php new file mode 100644 index 0000000000..d0dda89167 --- /dev/null +++ b/tests/text_processing/strip_bbcode_test.php @@ -0,0 +1,38 @@ +assertSame($expected, $actual, '20m4ill1'); + } + + public function test_s9e() + { + $phpbb_container = $this->get_test_case_helpers()->set_s9e_services(); + + $original = '[b]bold[/b]'; + $expected = ' bold '; + + $actual = $original; + strip_bbcode($actual); + + $this->assertSame($expected, $actual); + } +} diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.html b/tests/text_processing/tickets_data/PHPBB3-10002.html new file mode 100644 index 0000000000..82990b2253 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10002.html @@ -0,0 +1,2 @@ +
          • one +
            • two
          \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.txt b/tests/text_processing/tickets_data/PHPBB3-10002.txt new file mode 100644 index 0000000000..fe2f29073f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10002.txt @@ -0,0 +1,2 @@ +[quote][list][*]one +[quote][list][*]two[/list][/quote] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.html b/tests/text_processing/tickets_data/PHPBB3-10425.html new file mode 100644 index 0000000000..522b2f8858 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10425.html @@ -0,0 +1,3 @@ +http://ar.wikipedia.org/wiki/الصفحة_الرئيسية
          +http://ar.wikipedia.org/wiki/الصفحة_الرئيسية
          +link \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.txt b/tests/text_processing/tickets_data/PHPBB3-10425.txt new file mode 100644 index 0000000000..d93c0446b6 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10425.txt @@ -0,0 +1,3 @@ +http://ar.wikipedia.org/wiki/الصفحة_الرئيسية +[url]http://ar.wikipedia.org/wiki/الصفحة_الرئيسية[/url] +[url=http://ar.wikipedia.org/wiki/الصفحة_الرئيسية]link[/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.html b/tests/text_processing/tickets_data/PHPBB3-10587.html new file mode 100644 index 0000000000..dd0a483244 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10587.html @@ -0,0 +1,2 @@ +http://www.tx-gaming.net/warzone/tournament.php?tourney[id]=34&action=brackets
          +link \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.txt b/tests/text_processing/tickets_data/PHPBB3-10587.txt new file mode 100644 index 0000000000..f81a35eb5f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10587.txt @@ -0,0 +1,2 @@ +[url]http://www.tx-gaming.net/warzone/tournament.php?tourney[id]=34&action=brackets[/url] +[url="http://www.tx-gaming.net/warzone/tournament.php?tourney[id]=34&action=brackets"]link[/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html new file mode 100644 index 0000000000..cdf8316df0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -0,0 +1 @@ +user@example.org... \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt new file mode 100644 index 0000000000..348f8a1541 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt @@ -0,0 +1 @@ +[email]user@example.org[/email][email=user@example.org]...[/email] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.html b/tests/text_processing/tickets_data/PHPBB3-10989.html new file mode 100644 index 0000000000..f003ad3dfa --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10989.html @@ -0,0 +1,8 @@ +
          Lorem wrote:[quote="Lorem"
          Suspendisse iaculis porta tempor. Nulla.
          + Nullam a tortor sit amet.
          + Proin ac mi eget magna. + +
          Lorem wrote:Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.
          + +
          +Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper. \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.txt b/tests/text_processing/tickets_data/PHPBB3-10989.txt new file mode 100644 index 0000000000..dc2430f210 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10989.txt @@ -0,0 +1,8 @@ +[quote="Lorem"][quote="Lorem"[quote] Suspendisse iaculis porta tempor. Nulla.[/quote] + Nullam a tortor sit amet.[/quote] + Proin ac mi eget magna. + +[quote="Lorem"]Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.[/quote] + + +Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper. \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.html b/tests/text_processing/tickets_data/PHPBB3-11153.html new file mode 100644 index 0000000000..0f67ac4bc0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.html @@ -0,0 +1 @@ +... \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.txt b/tests/text_processing/tickets_data/PHPBB3-11153.txt new file mode 100644 index 0000000000..d2794978d9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.txt @@ -0,0 +1 @@ +[myemail=user@example.org]...[/myemail] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.xml b/tests/text_processing/tickets_data/PHPBB3-11153.xml new file mode 100644 index 0000000000..a7fc69520b --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.xml @@ -0,0 +1,28 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + myemail + + 1 + [myemail={EMAIL}]{TEXT}[/myemail] + {TEXT}]]> + + bbcode_specialchars('${1}').':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${2}')).'[/myemail:$uid]']]> + + ${2}]]> + +
          +
          diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.html b/tests/text_processing/tickets_data/PHPBB3-12195.html new file mode 100644 index 0000000000..d8e0f8d523 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12195.html @@ -0,0 +1 @@ +Image \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.txt b/tests/text_processing/tickets_data/PHPBB3-12195.txt new file mode 100644 index 0000000000..b66dbd5d96 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12195.txt @@ -0,0 +1 @@ +[url=//example.org/][img]//example.org/img.png[/img][/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.before.php b/tests/text_processing/tickets_data/PHPBB3-3981.before.php new file mode 100644 index 0000000000..20c96d163c --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.before.php @@ -0,0 +1,17 @@ +markTestSkipped('International URLs need idn_to_ascii()'); + } +} diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.html b/tests/text_processing/tickets_data/PHPBB3-3981.html new file mode 100644 index 0000000000..e5f1b4561d --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.html @@ -0,0 +1 @@ +http://www.ööö.com \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.txt b/tests/text_processing/tickets_data/PHPBB3-3981.txt new file mode 100644 index 0000000000..976823f1d1 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.txt @@ -0,0 +1 @@ +[url]http://www.ööö.com[/url] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.html b/tests/text_processing/tickets_data/PHPBB3-7187.html new file mode 100644 index 0000000000..9138779d29 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.html @@ -0,0 +1 @@ +
          :geek: :ugeek:
          \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.txt b/tests/text_processing/tickets_data/PHPBB3-7187.txt new file mode 100644 index 0000000000..584151a083 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.txt @@ -0,0 +1 @@ +[quote]:geek: :ugeek:[/quote] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.xml b/tests/text_processing/tickets_data/PHPBB3-7187.xml new file mode 100644 index 0000000000..d270b12619 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.xml @@ -0,0 +1,33 @@ + + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 41 + :geek: + Geek + icon_e_geek.gif + 17 + 17 + 41 + 1 + + + 42 + :ugeek: + Uber Geek + icon_e_ugeek.gif + 17 + 18 + 42 + 1 + +
          +
          diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.after.php b/tests/text_processing/tickets_data/PHPBB3-7275.after.php new file mode 100644 index 0000000000..a824cb9b84 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.after.php @@ -0,0 +1,15 @@ +assertSame($original, $parsed_text); +} diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.html b/tests/text_processing/tickets_data/PHPBB3-7275.html new file mode 100644 index 0000000000..12502833fd --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.html @@ -0,0 +1 @@ +
          :)
          \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.txt b/tests/text_processing/tickets_data/PHPBB3-7275.txt new file mode 100644 index 0000000000..8de97d67e0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.txt @@ -0,0 +1 @@ +[center]:)[/center] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.xml b/tests/text_processing/tickets_data/PHPBB3-7275.xml new file mode 100644 index 0000000000..9e979afffb --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.xml @@ -0,0 +1,49 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + center + + 1 + [center]{TEXT}[/center] + {TEXT}]]> + !\[center\](.*?)\[/center\]!ies + + !\[center:$uid\](.*?)\[/center:$uid\]!s + ${1}]]> + +
          + + + smiley_id + code + emotion + smiley_url + smiley_width + smiley_height + smiley_order + display_on_posting + + 4 + :) + Smile + icon_e_smile.gif + 15 + 17 + 4 + 1 + +
          +
          diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.html b/tests/text_processing/tickets_data/PHPBB3-9377.html new file mode 100644 index 0000000000..dcfb79c173 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.html @@ -0,0 +1 @@ +red blue red \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.txt b/tests/text_processing/tickets_data/PHPBB3-9377.txt new file mode 100644 index 0000000000..dfd71492c5 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.txt @@ -0,0 +1 @@ +[red]red [blue]blue[/blue] red[/red] \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.xml b/tests/text_processing/tickets_data/PHPBB3-9377.xml new file mode 100644 index 0000000000..1d8ee3d53f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.xml @@ -0,0 +1,41 @@ + + + + bbcode_id + bbcode_tag + bbcode_helpline + display_on_posting + bbcode_match + bbcode_tpl + first_pass_match + first_pass_replace + second_pass_match + second_pass_replace + + + 13 + red + + 1 + [red]{TEXT}[/red] + <span style="color:red">{TEXT}</span> + !\[red\](.*?)\[/red\]!ies + '[red:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/red:$uid]' + !\[red:$uid\](.*?)\[/red:$uid\]!s + <span style="color:red">${1}</span> + + + + 14 + blue + + 1 + [blue]{TEXT}[/blue] + <span style="color:blue">{TEXT}</span> + !\[blue\](.*?)\[/blue\]!ies + '[blue:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/blue:$uid]' + !\[blue:$uid\](.*?)\[/blue:$uid\]!s + <span style="color:blue">${1}</span> + +
          +
          diff --git a/tests/text_processing/tickets_test.php b/tests/text_processing/tickets_test.php new file mode 100644 index 0000000000..d2072a10f5 --- /dev/null +++ b/tests/text_processing/tickets_test.php @@ -0,0 +1,91 @@ +get_test_case_helpers()->set_s9e_services($phpbb_container, $fixture); + + $parser = $phpbb_container->get('text_formatter.parser'); + $renderer = $phpbb_container->get('text_formatter.renderer'); + + if (isset($before_assert)) + { + $test = $this; + $before_assert(get_defined_vars()); + } + + $parsed_text = $parser->parse($original); + + $this->assertSame($expected, $renderer->render($parsed_text)); + + if (isset($after_assert)) + { + $test = $this; + $after_assert(get_defined_vars()); + } + } + + public function get_tickets_data() + { + $tests = array(); + + foreach (glob(__DIR__ . '/tickets_data/*.txt') as $txt_filename) + { + $ticket_id = basename($txt_filename, '.txt'); + $html_filename = substr($txt_filename, 0, -3) . 'html'; + $xml_filename = substr($txt_filename, 0, -3) . 'xml'; + $before_filename = substr($txt_filename, 0, -3) . 'before.php'; + $after_filename = substr($txt_filename, 0, -3) . 'after.php'; + + if (!file_exists($xml_filename)) + { + $xml_filename = __DIR__ . '/../fixtures/empty.xml'; + } + + $before_assert = null; + if (file_exists($before_filename)) + { + include($before_filename); + $before_assert = 'before_assert_' . strtolower(str_replace('-', '_', $ticket_id)); + } + + $after_assert = null; + if (file_exists($after_filename)) + { + include($after_filename); + $after_assert = 'after_assert_' . strtolower(str_replace('-', '_', $ticket_id)); + } + + $tests[] = array( + $ticket_id, + file_get_contents($txt_filename), + file_get_contents($html_filename), + $xml_filename, + $before_assert, + $after_assert + ); + } + + return $tests; + } +}