aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb/textformatter
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/phpbb/textformatter')
-rw-r--r--phpBB/phpbb/textformatter/s9e/factory.php124
-rw-r--r--phpBB/phpbb/textformatter/s9e/link_helper.php118
-rw-r--r--phpBB/phpbb/textformatter/s9e/parser.php13
-rw-r--r--phpBB/phpbb/textformatter/s9e/quote_helper.php81
-rw-r--r--phpBB/phpbb/textformatter/s9e/renderer.php63
-rw-r--r--phpBB/phpbb/textformatter/s9e/utils.php54
-rw-r--r--phpBB/phpbb/textformatter/utils_interface.php15
7 files changed, 396 insertions, 72 deletions
diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php
index 9576abe1f0..8c273c342e 100644
--- a/phpBB/phpbb/textformatter/s9e/factory.php
+++ b/phpBB/phpbb/textformatter/s9e/factory.php
@@ -23,6 +23,11 @@ use s9e\TextFormatter\Configurator\Items\UnsafeTemplate;
class factory implements \phpbb\textformatter\cache_interface
{
/**
+ * @var \phpbb\textformatter\s9e\link_helper
+ */
+ protected $link_helper;
+
+ /**
* @var \phpbb\cache\driver\driver_interface
*/
protected $cache;
@@ -43,6 +48,11 @@ class factory implements \phpbb\textformatter\cache_interface
protected $cache_key_renderer;
/**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
* @var array Custom tokens used in bbcode.html and their corresponding token from the definition
*/
protected $custom_tokens = array(
@@ -66,9 +76,9 @@ class factory implements \phpbb\textformatter\cache_interface
protected $default_definitions = array(
'attachment' => '[ATTACHMENT index={NUMBER} filename={TEXT;useContent}]',
'b' => '[B]{TEXT}[/B]',
- 'code' => '[CODE]{TEXT}[/CODE]',
+ 'code' => '[CODE lang={IDENTIFIER;optional}]{TEXT}[/CODE]',
'color' => '[COLOR={COLOR}]{TEXT}[/COLOR]',
- 'email' => '[EMAIL={EMAIL;useContent}]{TEXT}[/EMAIL]',
+ 'email' => '[EMAIL={EMAIL;useContent} subject={TEXT;optional;postFilter=rawurlencode} body={TEXT;optional;postFilter=rawurlencode}]{TEXT}[/EMAIL]',
'flash' => '[FLASH={NUMBER1},{NUMBER2} width={NUMBER1;postFilter=#flashwidth} height={NUMBER2;postFilter=#flashheight} url={URL;useContent} /]',
'i' => '[I]{TEXT}[/I]',
'img' => '[IMG src={IMAGEURL;useContent}]',
@@ -77,14 +87,19 @@ 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}
]{TEXT2}[/QUOTE]",
'size' => '[SIZE={FONTSIZE}]{TEXT}[/SIZE]',
'u' => '[U]{TEXT}[/U]',
- 'url' => '[URL={URL;useContent}]{TEXT}[/URL]',
+ 'url' => '[URL={URL;useContent} $forceLookahead=true]{TEXT}[/URL]',
);
/**
@@ -94,10 +109,21 @@ class factory implements \phpbb\textformatter\cache_interface
'b' => '<span style="font-weight: bold"><xsl:apply-templates/></span>',
'i' => '<span style="font-style: italic"><xsl:apply-templates/></span>',
'u' => '<span style="text-decoration: underline"><xsl:apply-templates/></span>',
- 'img' => '<img src="{IMAGEURL}" alt="{L_IMAGE}"/>',
+ 'img' => '<img src="{IMAGEURL}" class="postimage" alt="{L_IMAGE}"/>',
'size' => '<span style="font-size: {FONTSIZE}%; line-height: normal"><xsl:apply-templates/></span>',
'color' => '<span style="color: {COLOR}"><xsl:apply-templates/></span>',
- 'email' => '<a href="mailto:{EMAIL}"><xsl:apply-templates/></a>',
+ 'email' => '<a>
+ <xsl:attribute name="href">
+ <xsl:text>mailto:</xsl:text>
+ <xsl:value-of select="@email"/>
+ <xsl:if test="@subject or @body">
+ <xsl:text>?</xsl:text>
+ <xsl:if test="@subject">subject=<xsl:value-of select="@subject"/></xsl:if>
+ <xsl:if test="@body"><xsl:if test="@subject">&amp;</xsl:if>body=<xsl:value-of select="@body"/></xsl:if>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </a>',
);
/**
@@ -111,16 +137,20 @@ class factory implements \phpbb\textformatter\cache_interface
* @param \phpbb\textformatter\data_access $data_access
* @param \phpbb\cache\driver\driver_interface $cache
* @param \phpbb\event\dispatcher_interface $dispatcher
+ * @param \phpbb\config\config $config
+ * @param \phpbb\textformatter\s9e\link_helper $link_helper
* @param string $cache_dir Path to the cache dir
* @param string $cache_key_parser Cache key used for the parser
* @param string $cache_key_renderer Cache key used for the renderer
*/
- public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, \phpbb\event\dispatcher_interface $dispatcher, $cache_dir, $cache_key_parser, $cache_key_renderer)
+ public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\config\config $config, \phpbb\textformatter\s9e\link_helper $link_helper, $cache_dir, $cache_key_parser, $cache_key_renderer)
{
+ $this->link_helper = $link_helper;
$this->cache = $cache;
$this->cache_dir = $cache_dir;
$this->cache_key_parser = $cache_key_parser;
$this->cache_key_renderer = $cache_key_renderer;
+ $this->config = $config;
$this->data_access = $data_access;
$this->dispatcher = $dispatcher;
}
@@ -174,6 +204,16 @@ class factory implements \phpbb\textformatter\cache_interface
$vars = array('configurator');
extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_before', compact($vars)));
+ // Reset the list of allowed schemes
+ foreach ($configurator->urlConfig->getAllowedSchemes() as $scheme)
+ {
+ $configurator->urlConfig->disallowScheme($scheme);
+ }
+ foreach (explode(',', $this->config['allowed_schemes_links']) as $scheme)
+ {
+ $configurator->urlConfig->allowScheme(trim($scheme));
+ }
+
// Convert newlines to br elements by default
$configurator->rootRules->enableAutoLineBreaks();
@@ -299,8 +339,7 @@ class factory implements \phpbb\textformatter\cache_interface
}
// Load the magic links plugins. We do that after BBCodes so that they use the same tags
- $configurator->plugins->load('Autoemail');
- $configurator->plugins->load('Autolink', array('matchWww' => true));
+ $this->configure_autolink($configurator);
// Register some vars with a default value. Those should be set at runtime by whatever calls
// the parser
@@ -308,6 +347,11 @@ class factory implements \phpbb\textformatter\cache_interface
$configurator->registeredVars['max_img_height'] = 0;
$configurator->registeredVars['max_img_width'] = 0;
+ // Load the Emoji plugin and modify its tag's template to obey viewsmilies
+ $configurator->Emoji->setImageSize(18);
+ $tag = $configurator->Emoji->getTag();
+ $tag->template = '<xsl:choose><xsl:when test="$S_VIEWSMILIES">' . str_replace('class="emoji"', 'class="smilies"', $tag->template) . '</xsl:when><xsl:otherwise><xsl:value-of select="."/></xsl:otherwise></xsl:choose>';
+
/**
* Modify the s9e\TextFormatter configurator after the default settings are set
*
@@ -357,6 +401,47 @@ class factory implements \phpbb\textformatter\cache_interface
}
/**
+ * Configure the Autolink / Autoemail plugins used to linkify text
+ *
+ * @param \s9e\TextFormatter\Configurator $configurator
+ * @return void
+ */
+ protected function configure_autolink(Configurator $configurator)
+ {
+ $configurator->plugins->load('Autoemail');
+ $configurator->plugins->load('Autolink', array('matchWww' => true));
+
+ // Add a tag filter that creates a tag that stores and replace the
+ // content of a link created by the Autolink plugin
+ $configurator->Autolink->getTag()->filterChain
+ ->add(array($this->link_helper, 'generate_link_text_tag'))
+ ->resetParameters()
+ ->addParameterByName('tag')
+ ->addParameterByName('parser');
+
+ // Create a tag that will be used to display the truncated text by
+ // replacing the original content with the content of the @text attribute
+ $tag = $configurator->tags->add('LINK_TEXT');
+ $tag->attributes->add('text');
+ $tag->template = '<xsl:value-of select="@text"/>';
+
+ $tag->filterChain
+ ->add(array($this->link_helper, 'truncate_local_url'))
+ ->resetParameters()
+ ->addParameterByName('tag')
+ ->addParameterByValue(generate_board_url() . '/');
+ $tag->filterChain
+ ->add(array($this->link_helper, 'truncate_text'))
+ ->resetParameters()
+ ->addParameterByName('tag');
+ $tag->filterChain
+ ->add(array($this->link_helper, 'cleanup_tag'))
+ ->resetParameters()
+ ->addParameterByName('tag')
+ ->addParameterByName('parser');
+ }
+
+ /**
* Return the default BBCodes configuration
*
* @return array 2D array. Each element has a 'usage' key, a 'template' key, and an optional 'options' key
@@ -460,24 +545,11 @@ class factory implements \phpbb\textformatter\cache_interface
$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()
diff --git a/phpBB/phpbb/textformatter/s9e/link_helper.php b/phpBB/phpbb/textformatter/s9e/link_helper.php
new file mode 100644
index 0000000000..0f44603dec
--- /dev/null
+++ b/phpBB/phpbb/textformatter/s9e/link_helper.php
@@ -0,0 +1,118 @@
+<?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 link_helper
+{
+ /**
+ * Clean up and invalidate a LINK_TEXT tag if applicable
+ *
+ * Will invalidate the tag if its replacement text is the same as the original
+ * text and would have no visible effect
+ *
+ * @param \s9e\TextFormatter\Parser\Tag $tag LINK_TEXT tag
+ * @param \s9e\TextFormatter\Parser $parser Parser
+ * @return bool Whether the tag is valid
+ */
+ public function cleanup_tag(\s9e\TextFormatter\Parser\Tag $tag, \s9e\TextFormatter\Parser $parser)
+ {
+ // Invalidate if the content of the tag matches the text attribute
+ $text = substr($parser->getText(), $tag->getPos(), $tag->getLen());
+
+ return ($text !== $tag->getAttribute('text'));
+ }
+
+ /**
+ * Create a LINK_TEXT tag inside of a link
+ *
+ * Meant to only apply to linkified URLs and [url] BBCodes without a parameter
+ *
+ * @param \s9e\TextFormatter\Parser\Tag $tag URL tag (start tag)
+ * @param \s9e\TextFormatter\Parser $parser Parser
+ * @return bool Always true to indicate that the tag is valid
+ */
+ public function generate_link_text_tag(\s9e\TextFormatter\Parser\Tag $tag, \s9e\TextFormatter\Parser $parser)
+ {
+ // Only create a LINK_TEXT tag if the start tag is paired with an end
+ // tag, which is the case with tags from the Autolink plugins and with
+ // the [url] BBCode when its content is used for the URL
+ if (!$tag->getEndTag() || !$this->should_shorten($tag, $parser->getText()))
+ {
+ return true;
+ }
+
+ // Capture the text between the start tag and its end tag
+ $start = $tag->getPos() + $tag->getLen();
+ $end = $tag->getEndTag()->getPos();
+ $length = $end - $start;
+ $text = substr($parser->getText(), $start, $length);
+
+ // Create a tag that consumes the link's text
+ $parser->addSelfClosingTag('LINK_TEXT', $start, $length)->setAttribute('text', $text);
+
+ return true;
+ }
+
+ /**
+ * Test whether we should shorten this tag's text
+ *
+ * Will test whether the tag either does not use any markup or uses a single
+ * [url] BBCode
+ *
+ * @param \s9e\TextFormatter\Parser\Tag $tag URL tag
+ * @param string $text Original text
+ * @return bool
+ */
+ protected function should_shorten(\s9e\TextFormatter\Parser\Tag $tag, $text)
+ {
+ return ($tag->getLen() === 0 || strtolower(substr($text, $tag->getPos(), $tag->getLen())) === '[url]');
+ }
+
+ /**
+ * Remove the board's root URL from a the start of a string
+ *
+ * @param \s9e\TextFormatter\Parser\Tag $tag LINK_TEXT tag
+ * @param string $board_url Forum's root URL (with trailing slash)
+ * @return bool Always true to indicate that the tag is valid
+ */
+ public function truncate_local_url(\s9e\TextFormatter\Parser\Tag $tag, $board_url)
+ {
+ $text = $tag->getAttribute('text');
+ if (stripos($text, $board_url) === 0 && strlen($text) > strlen($board_url))
+ {
+ $tag->setAttribute('text', substr($text, strlen($board_url)));
+ }
+
+ return true;
+ }
+
+ /**
+ * Truncate the replacement text set in a LINK_TEXT tag
+ *
+ * @param \s9e\TextFormatter\Parser\Tag $tag LINK_TEXT tag
+ * @return bool Always true to indicate that the tag is valid
+ */
+ public function truncate_text(\s9e\TextFormatter\Parser\Tag $tag)
+ {
+ $text = $tag->getAttribute('text');
+ if (utf8_strlen($text) > 55)
+ {
+ $text = utf8_substr($text, 0, 39) . ' ... ' . utf8_substr($text, -10);
+ }
+
+ $tag->setAttribute('text', $text);
+
+ return true;
+ }
+}
diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php
index b7d0b2b90b..e2653d60f0 100644
--- a/phpBB/phpbb/textformatter/s9e/parser.php
+++ b/phpBB/phpbb/textformatter/s9e/parser.php
@@ -50,6 +50,7 @@ class parser implements \phpbb\textformatter\parser_interface
$this->dispatcher = $dispatcher;
$this->parser = $parser;
+
$parser = $this;
/**
@@ -195,7 +196,7 @@ class parser implements \phpbb\textformatter\parser_interface
$errors = array();
foreach ($this->parser->getLogger()->get() as $entry)
{
- list($type, $msg, $context) = $entry;
+ list(, $msg, $context) = $entry;
if ($msg === 'Tag limit exceeded')
{
@@ -227,7 +228,13 @@ class parser implements \phpbb\textformatter\parser_interface
}
}
- return array_unique($errors);
+ // Deduplicate error messages. array_unique() only works on strings so we have to serialize
+ if (!empty($errors))
+ {
+ $errors = array_map('unserialize', array_unique(array_map('serialize', $errors)));
+ }
+
+ return $errors;
}
/**
@@ -364,7 +371,7 @@ class parser implements \phpbb\textformatter\parser_interface
if ($max_height || $max_width)
{
- $imagesize = new \fastImageSize\fastImageSize();
+ $imagesize = new \FastImageSize\FastImageSize();
$size_info = $imagesize->getImageSize($url);
if ($size_info === false)
{
diff --git a/phpBB/phpbb/textformatter/s9e/quote_helper.php b/phpBB/phpbb/textformatter/s9e/quote_helper.php
new file mode 100644
index 0000000000..24109ac8cc
--- /dev/null
+++ b/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;
+ }
+ );
+ }
+}
diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php
index 8999f1d25f..9be20b7f53 100644
--- a/phpBB/phpbb/textformatter/s9e/renderer.php
+++ b/phpBB/phpbb/textformatter/s9e/renderer.php
@@ -29,6 +29,11 @@ class renderer implements \phpbb\textformatter\renderer_interface
protected $dispatcher;
/**
+ * @var quote_helper
+ */
+ protected $quote_helper;
+
+ /**
* @var \s9e\TextFormatter\Renderer
*/
protected $renderer;
@@ -113,6 +118,16 @@ class renderer implements \phpbb\textformatter\renderer_interface
}
/**
+ * 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
*
* @param \phpbb\config\config $config
@@ -214,6 +229,11 @@ class renderer implements \phpbb\textformatter\renderer_interface
*/
public function render($xml)
{
+ if (isset($this->quote_helper))
+ {
+ $xml = $this->quote_helper->inject_metadata($xml);
+ }
+
$renderer = $this;
/**
@@ -234,10 +254,6 @@ class renderer implements \phpbb\textformatter\renderer_interface
}
$html = $this->renderer->render($xml);
- if (stripos($html, '<code') !== false)
- {
- $html = $this->replace_tabs_in_code($html);
- }
/**
* Modify a rendered text
@@ -254,45 +270,6 @@ class renderer implements \phpbb\textformatter\renderer_interface
}
/**
- * Replace tabs in code elements
- *
- * @see bbcode::bbcode_second_pass_code()
- *
- * @param string $html Original HTML
- * @return string Modified HTML
- */
- protected function replace_tabs_in_code($html)
- {
- return preg_replace_callback(
- '((<code[^>]*>)(.*?)(</code>))is',
- function ($captures)
- {
- $code = $captures[2];
-
- $code = str_replace("\t", '&nbsp; &nbsp;', $code);
- $code = str_replace(' ', '&nbsp; ', $code);
- $code = str_replace(' ', ' &nbsp;', $code);
- $code = str_replace("\n ", "\n&nbsp;", $code);
-
- // keep space at the beginning
- if (!empty($code) && $code[0] == ' ')
- {
- $code = '&nbsp;' . 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
- );
- }
-
- /**
* {@inheritdoc}
*/
public function set_smilies_path($path)
diff --git a/phpBB/phpbb/textformatter/s9e/utils.php b/phpBB/phpbb/textformatter/s9e/utils.php
index e21dedecc4..b317fe4a8d 100644
--- a/phpBB/phpbb/textformatter/s9e/utils.php
+++ b/phpBB/phpbb/textformatter/s9e/utils.php
@@ -35,6 +35,60 @@ class utils implements \phpbb\textformatter\utils_interface
}
/**
+ * 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
+ */
+ 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, '\\"') . '"';
+
+ return (strlen($singleQuoted) < strlen($doubleQuoted)) ? $singleQuoted : $doubleQuoted;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function generate_quote($text, array $attributes = array())
+ {
+ $text = trim($text);
+ $quote = '[quote';
+ if (isset($attributes['author']))
+ {
+ // Add the author as the BBCode's default attribute
+ $quote .= '=' . $this->format_attribute_value($attributes['author']);
+ unset($attributes['author']);
+ }
+
+ if (isset($attributes['user_id']) && $attributes['user_id'] == ANONYMOUS)
+ {
+ unset($attributes['user_id']);
+ }
+
+ ksort($attributes);
+ foreach ($attributes as $name => $value)
+ {
+ $quote .= ' ' . $name . '=' . $this->format_attribute_value($value);
+ }
+ $quote .= ']';
+ $newline = (strlen($quote . $text . '[/quote]') > 80 || strpos($text, "\n") !== false) ? "\n" : '';
+ $quote .= $newline . $text . $newline . '[/quote]';
+
+ return $quote;
+ }
+
+ /**
* Get a list of quote authors, limited to the outermost quotes
*
* @param string $xml Parsed text
diff --git a/phpBB/phpbb/textformatter/utils_interface.php b/phpBB/phpbb/textformatter/utils_interface.php
index 6d3fd13021..4810453cd1 100644
--- a/phpBB/phpbb/textformatter/utils_interface.php
+++ b/phpBB/phpbb/textformatter/utils_interface.php
@@ -29,6 +29,21 @@ interface utils_interface
public function clean_formatting($text);
/**
+ * 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 array $attributes Quote's attributes
+ * @return string Quote block to be used in a new post/text
+ */
+ public function generate_quote($text, array $attributes = array());
+
+ /**
* Get a list of quote authors, limited to the outermost quotes
*
* @param string $text Parsed text