Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ticket/10620] Quote improvements #3623

Merged
merged 10 commits into from Jul 7, 2015
64 changes: 60 additions & 4 deletions phpBB/assets/javascript/editor.js
Expand Up @@ -111,7 +111,6 @@ function bbfontstyle(bbopen, bbclose) {
}

textarea.focus();
return;
}

/**
Expand Down Expand Up @@ -167,7 +166,7 @@ function attachInline(index, filename) {
/**
* Add quote text to message
*/
function addquote(post_id, username, l_wrote) {
function addquote(post_id, username, l_wrote, attributes) {
var message_name = 'message_' + post_id;
var theSelection = '';
var divarea = false;
Expand All @@ -177,6 +176,9 @@ function addquote(post_id, username, l_wrote) {
// Backwards compatibility
l_wrote = 'wrote';
}
if (typeof attributes !== 'object') {
attributes = {};
}

if (document.all) {
divarea = document.all[message_name];
Expand Down Expand Up @@ -213,7 +215,8 @@ function addquote(post_id, username, l_wrote) {

if (theSelection) {
if (bbcodeEnabled) {
insert_text('[quote="' + username + '"]' + theSelection + '[/quote]');
attributes.author = username;
insert_text(generateQuote(theSelection, attributes));
} else {
insert_text(username + ' ' + l_wrote + ':' + '\n');
var lines = split_lines(theSelection);
Expand All @@ -222,8 +225,61 @@ function addquote(post_id, username, l_wrote) {
}
}
}
}

return;
/**
* Create a quote block for given text
*
* Possible attributes:
* - author: author's name (usually a username)
* - post_id: post_id of the post being quoted
* - user_id: user_id of the user being quoted
* - time: timestamp of the original message
*
* @param {!string} text Quote's text
* @param {!Object} attributes Quote's attributes
* @return {!string} Quote block to be used in a new post/text
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk what syntax you're using in the docblock but it isn't JSDoc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I Googled "JSDoc type annotations" and got to this page: http://usejsdoc.org/tags-type.html

That looks like it. Do you want me to remove them or... ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I had never seen the exclamation mark syntax before :)

*/
function generateQuote(text, attributes) {
text = text.replace(/^\s+/, '').replace(/\s+$/, '');
var quote = '[quote';
if (attributes.author) {
// Add the author as the BBCode's default attribute
quote += '=' + formatAttributeValue(attributes.author);
delete attributes.author;
}
for (var name in attributes) {
if (attributes.hasOwnProperty(name)) {
var value = attributes[name];
quote += ' ' + name + '=' + formatAttributeValue(value.toString());
}
}
quote += ']';
var newline = ((quote + text + '[/quote]').length > 80 || text.indexOf('\n') > -1) ? '\n' : '';
quote += newline + text + newline + '[/quote]';

return quote;
}

/**
* Format given string to be used as an attribute value
*
* Will return the string as-is if it can be used in a BBCode without quotes. Otherwise,
* it will use either single- or double- quotes depending on whichever requires less escaping.
* Quotes and backslashes are escaped with backslashes where necessary
*
* @param {!string} str Original string
* @return {!string} Same string if possible, escaped string within quotes otherwise
*/
function formatAttributeValue(str) {
if (!/[ "'\\\]]/.test(str)) {
// Return as-is if it contains none of: space, ' " \ or ]
return str;
}
var singleQuoted = "'" + str.replace(/[\\']/g, '\\$&') + "'",
doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"';

return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted;
}

function split_lines(text) {
Expand Down
8 changes: 8 additions & 0 deletions phpBB/config/default/container/services_text_formatter.yml
Expand Up @@ -44,6 +44,13 @@ services:
- @text_formatter.s9e.factory
- @dispatcher

text_formatter.s9e.quote_helper:
class: phpbb\textformatter\s9e\quote_helper
arguments:
- @user
- %core.root_path%
- %core.php_ext%

text_formatter.s9e.renderer:
class: phpbb\textformatter\s9e\renderer
arguments:
Expand All @@ -53,6 +60,7 @@ services:
- @text_formatter.s9e.factory
- @dispatcher
calls:
- [configure_quote_helper, [@text_formatter.s9e.quote_helper]]
- [configure_smilies_path, [@config, @path_helper]]
- [configure_user, [@user, @config, @auth]]

Expand Down
2 changes: 2 additions & 0 deletions phpBB/includes/functions_posting.php
Expand Up @@ -1193,6 +1193,8 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
'MESSAGE' => $message,
'DECODED_MESSAGE' => $decoded_message,
'POST_ID' => $row['post_id'],
'POST_TIME' => $row['post_time'],
'USER_ID' => $row['user_id'],
'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=post_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '',
Expand Down
2 changes: 2 additions & 0 deletions phpBB/includes/functions_privmsgs.php
Expand Up @@ -2100,6 +2100,8 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode
'S_IN_POST_MODE' => $in_post_mode,

'MSG_ID' => $row['msg_id'],
'MESSAGE_TIME' => $row['message_time'],
'USER_ID' => $row['user_id'],
'U_VIEW_MESSAGE' => "$url&amp;f=$folder_id&amp;p=" . $row['msg_id'],
'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=quote&amp;f=" . $folder_id . "&amp;p=" . $row['msg_id'] : '',
'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $row['msg_id'] : '')
Expand Down
11 changes: 10 additions & 1 deletion phpBB/includes/ucp/ucp_pm_compose.php
Expand Up @@ -941,9 +941,18 @@ function compose_pm($id, $mode, $action, $user_folders = array())
{
$message_link = '';
}
$quote_attributes = array(
'author' => $quote_username,
'time' => $post['message_time'],
'user_id' => $post['author_id'],
);
if ($action === 'quotepost')
{
$quote_attributes['post_id'] = $post['msg_id'];
}
$quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote(
censor_text($message_parser->message),
array('author' => $quote_username)
$quote_attributes
);
$message_parser->message = $message_link . $quote_text . "\n\n";
}
Expand Down
28 changes: 10 additions & 18 deletions phpBB/phpbb/textformatter/s9e/factory.php
Expand Up @@ -77,7 +77,12 @@ class factory implements \phpbb\textformatter\cache_interface
'quote' =>
"[QUOTE
author={TEXT1;optional}
post_id={UINT;optional}
post_url={URL;optional;postFilter=#false}
profile_url={URL;optional;postFilter=#false}
time={UINT;optional}
url={URL;optional}
user_id={UINT;optional}
author={PARSE=/^\\[url=(?'url'.*?)](?'author'.*)\\[\\/url]$/i}
author={PARSE=/^\\[url](?'author'(?'url'.*?))\\[\\/url]$/i}
author={PARSE=/(?'url'https?:\\/\\/[^[\\]]+)/i}
Expand Down Expand Up @@ -471,24 +476,11 @@ protected function extract_templates($template)

$templates['li'] = $fragments['listitem'] . '<xsl:apply-templates/>' . $fragments['listitem_close'];

$fragments['quote_username_open'] = str_replace(
'{USERNAME}',
'<xsl:choose>
<xsl:when test="@url">' . str_replace('{DESCRIPTION}', '{USERNAME}', $fragments['url']) . '</xsl:when>
<xsl:otherwise>{USERNAME}</xsl:otherwise>
</xsl:choose>',
$fragments['quote_username_open']
);

$templates['quote'] =
'<xsl:choose>
<xsl:when test="@author">
' . $fragments['quote_username_open'] . '<xsl:apply-templates/>' . $fragments['quote_close'] . '
</xsl:when>
<xsl:otherwise>
' . $fragments['quote_open'] . '<xsl:apply-templates/>' . $fragments['quote_close'] . '
</xsl:otherwise>
</xsl:choose>';
// Replace the regular quote template with the extended quote template if available
if (isset($fragments['quote_extended']))
{
$templates['quote'] = $fragments['quote_extended'];
}

// The [attachment] BBCode uses the inline_attachment template to output a comment that
// is post-processed by parse_attachments()
Expand Down
81 changes: 81 additions & 0 deletions phpBB/phpbb/textformatter/s9e/quote_helper.php
@@ -0,0 +1,81 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @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;

class quote_helper
{
/**
* @var string Base URL for a post link, uses {POST_ID} as placeholder
*/
protected $post_url;

/**
* @var string Base URL for a profile link, uses {USER_ID} as placeholder
*/
protected $profile_url;

/**
* @var \phpbb\user
*/
protected $user;

/**
* Constructor
*
* @param \phpbb\user $user
* @param string $root_path
* @param string $php_ext
*/
public function __construct(\phpbb\user $user, $root_path, $php_ext)
{
$this->post_url = append_sid($root_path . 'viewtopic.' . $php_ext, 'p={POST_ID}#p{POST_ID}');
$this->profile_url = append_sid($root_path . 'memberlist.' . $php_ext, 'mode=viewprofile&u={USER_ID}');
$this->user = $user;
}

/**
* Inject dynamic metadata into QUOTE tags in given XML
*
* @param string $xml Original XML
* @return string Modified XML
*/
public function inject_metadata($xml)
{
$post_url = $this->post_url;
$profile_url = $this->profile_url;
$user = $this->user;

return \s9e\TextFormatter\Utils::replaceAttributes(
$xml,
'QUOTE',
function ($attributes) use ($post_url, $profile_url, $user)
{
if (isset($attributes['post_id']))
{
$attributes['post_url'] = str_replace('{POST_ID}', $attributes['post_id'], $post_url);
}
if (isset($attributes['time']))
{
$attributes['date'] = $user->format_date($attributes['time']);
}
if (isset($attributes['user_id']))
{
$attributes['profile_url'] = str_replace('{USER_ID}', $attributes['user_id'], $profile_url);
}

return $attributes;
}
);
}
}
19 changes: 19 additions & 0 deletions phpBB/phpbb/textformatter/s9e/renderer.php
Expand Up @@ -28,6 +28,11 @@ class renderer implements \phpbb\textformatter\renderer_interface
*/
protected $dispatcher;

/**
* @var quote_helper
*/
protected $quote_helper;

/**
* @var \s9e\TextFormatter\Renderer
*/
Expand Down Expand Up @@ -112,6 +117,16 @@ public function __construct(\phpbb\cache\driver\driver_interface $cache, $cache_
extract($dispatcher->trigger_event('core.text_formatter_s9e_renderer_setup', compact($vars)));
}

/**
* Configure the quote_helper object used to display extended information in quotes
*
* @param quote_helper $quote_helper
*/
public function configure_quote_helper(quote_helper $quote_helper)
{
$this->quote_helper = $quote_helper;
}

/**
* Automatically set the smilies path based on config
*
Expand Down Expand Up @@ -214,6 +229,10 @@ public function get_viewsmilies()
*/
public function render($xml)
{
if (isset($this->quote_helper))
{
$xml = $this->quote_helper->inject_metadata($xml);
}
$renderer = $this;

/**
Expand Down
19 changes: 13 additions & 6 deletions phpBB/phpbb/textformatter/s9e/utils.php
Expand Up @@ -35,16 +35,22 @@ public function clean_formatting($xml)
}

/**
* Return given string between quotes
* Format given string to be used as an attribute value
*
* Will use either single- or double- quotes depending on whichever requires less escaping.
* Will return the string as-is if it can be used in a BBCode without quotes. Otherwise,
* it will use either single- or double- quotes depending on whichever requires less escaping.
* Quotes and backslashes are escaped with backslashes where necessary
*
* @param string $str Original string
* @return string Escaped string within quotes
* @return string Same string if possible, escaped string within quotes otherwise
*/
protected function enquote($str)
protected function format_attribute_value($str)
{
if (!preg_match('/[ "\'\\\\\\]]/', $str))
{
// Return as-is if it contains none of: space, ' " \ or ]
return $str;
}
$singleQuoted = "'" . addcslashes($str, "\\'") . "'";
$doubleQuoted = '"' . addcslashes($str, '\\"') . '"';

Expand All @@ -61,12 +67,13 @@ public function generate_quote($text, array $attributes = array())
if (isset($attributes['author']))
{
// Add the author as the BBCode's default attribute
$quote .= '=' . $this->enquote($attributes['author']);
$quote .= '=' . $this->format_attribute_value($attributes['author']);
unset($attributes['author']);
}
ksort($attributes);
foreach ($attributes as $name => $value)
{
$quote .= ' ' . $name . '=' . $this->enquote($value);
$quote .= ' ' . $name . '=' . $this->format_attribute_value($value);
}
$quote .= ']';
$newline = (strlen($quote . $text . '[/quote]') > 80 || strpos($text, "\n") !== false) ? "\n" : '';
Expand Down
5 changes: 4 additions & 1 deletion phpBB/phpbb/textformatter/utils_interface.php
Expand Up @@ -32,7 +32,10 @@ public function clean_formatting($text);
* Create a quote block for given text
*
* Possible attributes:
* - author
* - author: author's name (usually a username)
* - post_id: post_id of the post being quoted
* - user_id: user_id of the user being quoted
* - time: timestamp of the original message
*
* @param string $text Quote's text
* @param array $attributes Quote's attributes
Expand Down
7 changes: 6 additions & 1 deletion phpBB/posting.php
Expand Up @@ -1605,7 +1605,12 @@
{
$message_parser->message = $phpbb_container->get('text_formatter.utils')->generate_quote(
censor_text($message_parser->message),
array('author' => $post_data['quote_username'])
array(
'author' => $post_data['quote_username'],
'post_id' => $post_data['post_id'],
'time' => $post_data['post_time'],
'user_id' => $post_data['poster_id'],
)
);
$message_parser->message .= "\n\n";
}
Expand Down