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
@@ -111,7 +111,6 @@ function bbfontstyle(bbopen, bbclose) {
}

textarea.focus();
return;
}

/**
@@ -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;
@@ -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];
@@ -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);
@@ -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

This comment has been minimized.

Copy link
@callumacrae

callumacrae Jun 25, 2015

Contributor

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

This comment has been minimized.

Copy link
@JoshyPHP

JoshyPHP Jun 25, 2015

Author Contributor

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... ?

This comment has been minimized.

Copy link
@callumacrae

callumacrae Jun 25, 2015

Contributor

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) {
@@ -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:
@@ -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]]

@@ -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'])) : '',
@@ -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'] : '')
@@ -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";
}
@@ -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}
@@ -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()
@@ -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;
}
);
}
}
@@ -28,6 +28,11 @@ class renderer implements \phpbb\textformatter\renderer_interface
*/
protected $dispatcher;
/**
* @var quote_helper
*/
protected $quote_helper;
/**
* @var \s9e\TextFormatter\Renderer
*/
@@ -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
*
@@ -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;
/**
@@ -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, '\\"') . '"';
@@ -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" : '';
@@ -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
@@ -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";
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.