diff options
48 files changed, 1207 insertions, 140 deletions
diff --git a/.travis.yml b/.travis.yml index 2d88c25b34..2f31eb74db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,6 +49,6 @@ script: - travis/check-image-icc-profiles.sh $DB $TRAVIS_PHP_VERSION $NOTESTS - travis/check-executable-files.sh $DB $TRAVIS_PHP_VERSION $NOTESTS ./ - sh -c "if [ '$SLOWTESTS' != '1' -a '$DB' = 'mysqli' ]; then phpBB/vendor/bin/phpunit tests/lint_test.php; fi" - - sh -c "if [ '$NOTESTS' != '1' -a '$SLOWTESTS' != '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml; fi" + - sh -c "if [ '$NOTESTS' != '1' -a '$SLOWTESTS' != '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml --verbose --stop-on-error; fi" - sh -c "if [ '$SLOWTESTS' = '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml --group slow; fi" - sh -c "set -x;if [ '$NOTESTS' = '1' -a '$TRAVIS_PULL_REQUEST' != 'false' ]; then git-tools/commit-msg-hook-range.sh origin/$TRAVIS_BRANCH..FETCH_HEAD; fi" diff --git a/phpBB/adm/style/acp_ext_details.html b/phpBB/adm/style/acp_ext_details.html index d7839f7ec8..bbddf2e6b6 100644 --- a/phpBB/adm/style/acp_ext_details.html +++ b/phpBB/adm/style/acp_ext_details.html @@ -19,6 +19,7 @@ </div> <!-- ENDIF --> <!-- ENDIF --> +<!-- EVENT acp_ext_details_notice --> <fieldset> <legend>{L_EXT_DETAILS}</legend> diff --git a/phpBB/adm/style/acp_jabber.html b/phpBB/adm/style/acp_jabber.html index 3c3b895624..e76c9a0323 100644 --- a/phpBB/adm/style/acp_jabber.html +++ b/phpBB/adm/style/acp_jabber.html @@ -47,6 +47,21 @@ <dd><label><input type="radio" class="radio" id="jab_use_ssl" name="jab_use_ssl" value="1"<!-- IF JAB_USE_SSL --> checked="checked"<!-- ENDIF --> /> {L_YES}</label> <label><input type="radio" class="radio" name="jab_use_ssl" value="0"<!-- IF not JAB_USE_SSL --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> </dl> +<dl> + <dt><label for="jab_verify_peer">{L_JAB_VERIFY_PEER}{L_COLON}</label><br /><span>{L_JAB_VERIFY_PEER_EXPLAIN}</span></dt> + <dd><label><input type="radio" class="radio" id="jab_verify_peer" name="jab_verify_peer" value="1"<!-- IF JAB_VERIFY_PEER --> checked="checked"<!-- ENDIF --> /> {L_YES}</label> + <label><input type="radio" class="radio" name="jab_verify_peer" value="0"<!-- IF not JAB_VERIFY_PEER --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> +</dl> +<dl> + <dt><label for="jab_verify_peer_name">{L_JAB_VERIFY_PEER_NAME}{L_COLON}</label><br /><span>{L_JAB_VERIFY_PEER_NAME_EXPLAIN}</span></dt> + <dd><label><input type="radio" class="radio" id="jab_verify_peer_name" name="jab_verify_peer_name" value="1"<!-- IF JAB_VERIFY_PEER_NAME --> checked="checked"<!-- ENDIF --> /> {L_YES}</label> + <label><input type="radio" class="radio" name="jab_verify_peer_name" value="0"<!-- IF not JAB_VERIFY_PEER_NAME --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> +</dl> +<dl> + <dt><label for="jab_allow_self_signed">{L_JAB_ALLOW_SELF_SIGNED}{L_COLON}</label><br /><span>{L_JAB_ALLOW_SELF_SIGNED_EXPLAIN}</span></dt> + <dd><label><input type="radio" class="radio" id="jab_allow_self_signed" name="jab_allow_self_signed" value="1"<!-- IF JAB_ALLOW_SELF_SIGNED --> checked="checked"<!-- ENDIF --> /> {L_YES}</label> + <label><input type="radio" class="radio" name="jab_allow_self_signed" value="0"<!-- IF not JAB_ALLOW_SELF_SIGNED --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> +</dl> <!-- ENDIF --> <dl> <dt><label for="jab_package_size">{L_JAB_PACKAGE_SIZE}{L_COLON}</label><br /><span>{L_JAB_PACKAGE_SIZE_EXPLAIN}</span></dt> diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index e306ce78e9..9522baa9c2 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -94,45 +94,15 @@ <!-- EVENT acp_main_notice_after --> - <table class="table1 no-header" style="width: auto;" data-no-responsive-header="true"> - <caption>{L_SOFTWARE_HEADING}</caption> - <col class="col1" /><col class="col2" /> - <thead> - <tr> - <th>{L_SOFTWARE_PRODUCT}</th> - <th>{L_SOFTWARE_VERSION}</th> - </tr> - </thead> - <tbody> - <tr> - <td>{L_BOARD_VERSION}</td> - <!-- IF S_VERSIONCHECK --> - <td><strong><a href="{U_VERSIONCHECK}" <!-- IF S_VERSION_UP_TO_DATE -->style="color: #228822;" <!-- ELSEIF not S_VERSIONCHECK_FAIL -->style="color: #BC2A4D;" <!-- ENDIF -->title="{L_MORE_INFORMATION}">{BOARD_VERSION}</a></strong> [ <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a> ] - </td> - <!-- ELSE --> - <td><strong>{BOARD_VERSION}</strong></td> - <!-- ENDIF --> - </tr> - <tr> - <td>{L_PHP_VERSION}</td> - <td><strong>{PHP_VERSION_INFO}</strong></td> - </tr> - <tr> - <td>{L_DATABASE_SERVER_INFO}</td> - <td><strong>{DATABASE_INFO}</strong></td> - </tr> - </tbody> - </table> - <table class="table1 two-columns no-header" data-no-responsive-header="true"> <caption>{L_FORUM_STATS}</caption> <col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" /> <thead> <tr> - <th style="width: 25%">{L_STATISTIC}</th> - <th style="width: 25%">{L_VALUE}</th> - <th style="width: 25%">{L_STATISTIC}</th> - <th style="width: 25%">{L_VALUE}</th> + <th>{L_STATISTIC}</th> + <th>{L_VALUE}</th> + <th>{L_STATISTIC}</th> + <th>{L_VALUE}</th> </tr> </thead> <tbody> @@ -173,8 +143,14 @@ <td><strong>{UPLOAD_DIR_SIZE}</strong></td> </tr> <tr> + <td>{L_DATABASE_SERVER_INFO}{L_COLON} </td> + <td><strong>{DATABASE_INFO}</strong></td> <td>{L_GZIP_COMPRESSION}{L_COLON} </td> <td><strong>{GZIP_COMPRESSION}</strong></td> + </tr> + <tr> + <td>{L_PHP_VERSION}{L_COLON} </td> + <td><strong>{PHP_VERSION_INFO}</strong></td> <!-- IF S_TOTAL_ORPHAN --> <td>{L_NUMBER_ORPHAN}{L_COLON} </td> <td><strong>{TOTAL_ORPHAN}</strong></td> @@ -183,6 +159,16 @@ <td> </td> <!-- ENDIF --> </tr> + <!-- IF S_VERSIONCHECK --> + <tr> + <td>{L_BOARD_VERSION}{L_COLON} </td> + <td> + <strong><a href="{U_VERSIONCHECK}" <!-- IF S_VERSION_UP_TO_DATE -->style="color: #228822;" <!-- ELSEIF not S_VERSIONCHECK_FAIL -->style="color: #BC2A4D;" <!-- ENDIF -->title="{L_MORE_INFORMATION}">{BOARD_VERSION}</a></strong> [ <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a> ] + </td> + <td> </td> + <td> </td> + </tr> + <!-- ENDIF --> </tbody> </table> diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index 9b0d70b46b..ef40e5f434 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -64,6 +64,12 @@ acp_ext_details_end * Since: 3.1.11-RC1 * Purpose: Add more detailed information on extension after the available information. +acp_ext_details_notice +=== +* Location: adm/style/acp_ext_details.html +* Since: 3.1.11-RC1 +* Purpose: Add extension detail notices after version check information. + acp_ext_list_disabled_name_after === * Location: adm/style/acp_ext_list.html @@ -688,6 +694,20 @@ forumlist_body_last_post_title_prepend * Since: 3.1.0-a1 * Purpose: Add content before the post title of the latest post in a forum on the forum list. +forumlist_body_subforum_link_append +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.1.11-RC1 +* Purpose: Add content at the end of subforum link item. + +forumlist_body_subforum_link_prepend +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.1.11-RC1 +* Purpose: Add content at the start of subforum link item. + forumlist_body_subforums_after === * Locations: @@ -709,6 +729,13 @@ forumlist_body_last_row_after * Since: 3.1.0-b2 * Purpose: Add content after the very last row of the forum list. +index_body_birthday_block_before +=== +* Locations: + + styles/prosilver/template/index_body.html +* Since: 3.1.11-RC1 +* Purpose: Add new statistic blocks before the Birthday block + index_body_block_birthday_append === * Locations: @@ -926,6 +953,20 @@ mcp_topic_postrow_post_details_before * Since: 3.1.10-RC1 * Purpose: Add content before post details in topic moderation +mcp_topic_postrow_post_subject_after +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.1.11-RC1 +* Purpose: Add content after post subject in topic moderation + +mcp_topic_postrow_post_subject_before +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.1.11-RC1 +* Purpose: Add content before post subject in topic moderation + mcp_topic_topic_title_after === * Locations: @@ -1813,6 +1854,13 @@ search_results_topic_before * Since: 3.1.0-b4 * Purpose: Add data before search result topics +search_results_topic_title_after +=== +* Locations: + + styles/prosilver/template/search_results.html +* Since: 3.1.11-RC1 +* Purpose: Add data after search results topic title + simple_footer_after === * Locations: diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 5c589222c6..6f65dc9fa0 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -106,7 +106,7 @@ class acp_extensions catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); - trigger_error($message, E_USER_WARNING); + trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING); } } @@ -161,7 +161,7 @@ class acp_extensions { $md_manager->validate_enable(); } - catch (\phpbb\extension\exception $e) + catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING); @@ -192,7 +192,7 @@ class acp_extensions { $md_manager->validate_enable(); } - catch (\phpbb\extension\exception $e) + catch (exception_interface $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING); @@ -216,6 +216,15 @@ class acp_extensions meta_refresh(0, $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name)); } } + + // Update custom style for admin area + $this->template->set_custom_style(array( + array( + 'name' => 'adm', + 'ext_path' => 'adm/style/', + ), + ), array($phpbb_root_path . 'adm/style')); + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_EXT_ENABLE', time(), array($ext_name)); } catch (\phpbb\db\migration\exception $e) diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index 5dec6bb7d4..07f5dadbff 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -49,13 +49,16 @@ class acp_jabber $this->tpl_name = 'acp_jabber'; $this->page_title = 'ACP_JABBER_SETTINGS'; - $jab_enable = $request->variable('jab_enable', (bool) $config['jab_enable']); - $jab_host = $request->variable('jab_host', (string) $config['jab_host']); - $jab_port = $request->variable('jab_port', (int) $config['jab_port']); - $jab_username = $request->variable('jab_username', (string) $config['jab_username']); - $jab_password = $request->variable('jab_password', (string) $config['jab_password']); - $jab_package_size = $request->variable('jab_package_size', (int) $config['jab_package_size']); - $jab_use_ssl = $request->variable('jab_use_ssl', (bool) $config['jab_use_ssl']); + $jab_enable = $request->variable('jab_enable', (bool) $config['jab_enable']); + $jab_host = $request->variable('jab_host', (string) $config['jab_host']); + $jab_port = $request->variable('jab_port', (int) $config['jab_port']); + $jab_username = $request->variable('jab_username', (string) $config['jab_username']); + $jab_password = $request->variable('jab_password', (string) $config['jab_password']); + $jab_package_size = $request->variable('jab_package_size', (int) $config['jab_package_size']); + $jab_use_ssl = $request->variable('jab_use_ssl', (bool) $config['jab_use_ssl']); + $jab_verify_peer = $request->variable('jab_verify_peer', (bool) $config['jab_verify_peer']); + $jab_verify_peer_name = $request->variable('jab_verify_peer_name', (bool) $config['jab_verify_peer_name']); + $jab_allow_self_signed = $request->variable('jab_allow_self_signed', (bool) $config['jab_allow_self_signed']); $form_name = 'acp_jabber'; add_form_key($form_name); @@ -73,7 +76,7 @@ class acp_jabber // Is this feature enabled? Then try to establish a connection if ($jab_enable) { - $jabber = new jabber($jab_host, $jab_port, $jab_username, $jab_password, $jab_use_ssl); + $jabber = new jabber($jab_host, $jab_port, $jab_username, $jab_password, $jab_use_ssl, $jab_verify_peer, $jab_verify_peer_name, $jab_allow_self_signed); if (!$jabber->connect()) { @@ -113,6 +116,9 @@ class acp_jabber } $config->set('jab_package_size', $jab_package_size); $config->set('jab_use_ssl', $jab_use_ssl); + $config->set('jab_verify_peer', $jab_verify_peer); + $config->set('jab_verify_peer_name', $jab_verify_peer_name); + $config->set('jab_allow_self_signed', $jab_allow_self_signed); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . $log); trigger_error($message . adm_back_link($this->u_action)); @@ -128,6 +134,9 @@ class acp_jabber 'JAB_PASSWORD' => $jab_password !== '' ? '********' : '', 'JAB_PACKAGE_SIZE' => $jab_package_size, 'JAB_USE_SSL' => $jab_use_ssl, + 'JAB_VERIFY_PEER' => $jab_verify_peer, + 'JAB_VERIFY_PEER_NAME' => $jab_verify_peer_name, + 'JAB_ALLOW_SELF_SIGNED' => $jab_allow_self_signed, 'S_CAN_USE_SSL' => jabber::can_use_ssl(), 'S_GTALK_NOTE' => (!@function_exists('dns_get_record')) ? true : false, )); diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 387606a300..c3e7a7ceb7 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -734,9 +734,11 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb * @var string uid The BBCode UID * @var string bitfield The BBCode Bitfield * @var int flags The BBCode Flags + * @var string message_parser The message_parser object * @since 3.1.0-a1 + * @changed 3.1.11-RC1 Added message_parser to vars */ - $vars = array('text', 'uid', 'bitfield', 'flags'); + $vars = array('text', 'uid', 'bitfield', 'flags', 'message_parser'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_storage_after', compact($vars))); return $message_parser->warn_msg; diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php index a38888a861..cfe8c2a90e 100644 --- a/phpBB/includes/functions_jabber.php +++ b/phpBB/includes/functions_jabber.php @@ -41,6 +41,9 @@ class jabber var $username; var $password; var $use_ssl; + var $verify_peer; + var $verify_peer_name; + var $allow_self_signed; var $resource = 'functions_jabber.phpbb.php'; var $enable_logging; @@ -49,8 +52,18 @@ class jabber var $features = array(); /** + * Constructor + * + * @param string $server Jabber server + * @param int $port Jabber server port + * @param string $username Jabber username or JID + * @param string $password Jabber password + * @param boold $use_ssl Use ssl + * @param bool $verify_peer Verify SSL certificate + * @param bool $verify_peer_name Verify Jabber peer name + * @param bool $allow_self_signed Allow self signed certificates */ - function jabber($server, $port, $username, $password, $use_ssl = false) + function __construct($server, $port, $username, $password, $use_ssl = false, $verify_peer = true, $verify_peer_name = true, $allow_self_signed = false) { $this->connect_server = ($server) ? $server : 'localhost'; $this->port = ($port) ? $port : 5222; @@ -71,6 +84,9 @@ class jabber $this->password = $password; $this->use_ssl = ($use_ssl && self::can_use_ssl()) ? true : false; + $this->verify_peer = $verify_peer; + $this->verify_peer_name = $verify_peer_name; + $this->allow_self_signed = $allow_self_signed; // Change port if we use SSL if ($this->port == 5222 && $this->use_ssl) @@ -95,7 +111,7 @@ class jabber */ static public function can_use_tls() { - if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('socket_set_blocking') || !function_exists('stream_get_wrappers')) + if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('stream_set_blocking') || !function_exists('stream_get_wrappers')) { return false; } @@ -138,7 +154,7 @@ class jabber $this->session['ssl'] = $this->use_ssl; - if ($this->open_socket($this->connect_server, $this->port, $this->use_ssl)) + if ($this->open_socket($this->connect_server, $this->port, $this->use_ssl, $this->verify_peer, $this->verify_peer_name, $this->allow_self_signed)) { $this->send("<?xml version='1.0' encoding='UTF-8' ?" . ">\n"); $this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n"); @@ -226,10 +242,13 @@ class jabber * @param string $server host to connect to * @param int $port port number * @param bool $use_ssl use ssl or not + * @param bool $verify_peer verify ssl certificate + * @param bool $verify_peer_name verify peer name + * @param bool $allow_self_signed allow self-signed ssl certificates * @access public * @return bool */ - function open_socket($server, $port, $use_ssl = false) + function open_socket($server, $port, $use_ssl, $verify_peer, $verify_peer_name, $allow_self_signed) { if (@function_exists('dns_get_record')) { @@ -240,12 +259,26 @@ class jabber } } - $server = $use_ssl ? 'ssl://' . $server : $server; + $options = array(); - if ($this->connection = @fsockopen($server, $port, $errorno, $errorstr, $this->timeout)) + if ($use_ssl) { - socket_set_blocking($this->connection, 0); - socket_set_timeout($this->connection, 60); + $remote_socket = 'ssl://' . $server . ':' . $port; + + // Set ssl context options, see http://php.net/manual/en/context.ssl.php + $options['ssl'] = array('verify_peer' => $verify_peer, 'verify_peer_name' => $verify_peer_name, 'allow_self_signed' => $allow_self_signed); + } + else + { + $remote_socket = $server . ':' . $port; + } + + $socket_context = stream_context_create($options); + + if ($this->connection = @stream_socket_client($remote_socket, $errorno, $errorstr, $this->timeout, STREAM_CLIENT_CONNECT, $socket_context)) + { + stream_set_blocking($this->connection, 0); + stream_set_timeout($this->connection, 60); return true; } @@ -562,7 +595,7 @@ class jabber case 'proceed': // continue switching to TLS $meta = stream_get_meta_data($this->connection); - socket_set_blocking($this->connection, 1); + stream_set_blocking($this->connection, 1); if (!stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { @@ -570,7 +603,7 @@ class jabber return false; } - socket_set_blocking($this->connection, $meta['blocked']); + stream_set_blocking($this->connection, $meta['blocked']); $this->session['tls'] = true; // new stream diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 802246c1c5..ab7f00a65a 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -306,10 +306,16 @@ class messenger /** * Send the mail out to the recipients set previously in var $this->addresses + * + * @param int $method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH + * @param bool $break Flag indicating if the function only formats the subject + * and the message without sending it + * + * @return bool */ function send($method = NOTIFY_EMAIL, $break = false) { - global $config, $user; + global $config, $user, $phpbb_dispatcher; // We add some standard variables we always use, no need to specify them always $this->assign_vars(array( @@ -318,6 +324,30 @@ class messenger 'SITENAME' => htmlspecialchars_decode($config['sitename']), )); + $subject = $this->subject; + $message = $this->msg; + /** + * Event to modify notification message text before parsing + * + * @event core.modify_notification_message + * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH + * @var bool break Flag indicating if the function only formats the subject + * and the message without sending it + * @var string subject The message subject + * @var string message The message text + * @since 3.1.11-RC1 + */ + $vars = array( + 'method', + 'break', + 'subject', + 'message', + ); + extract($phpbb_dispatcher->trigger_event('core.modify_notification_message', compact($vars))); + $this->subject = $subject; + $this->msg = $message; + unset($subject, $message); + // Parse message through template $this->msg = trim($this->template->assign_display('body')); @@ -618,7 +648,7 @@ class messenger if (!$use_queue) { include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); - $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], htmlspecialchars_decode($config['jab_password']), $config['jab_use_ssl']); + $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], htmlspecialchars_decode($config['jab_password']), $config['jab_use_ssl'], $config['jab_verify_peer'], $config['jab_verify_peer_name'], $config['jab_allow_self_signed']); if (!$this->jabber->connect()) { @@ -818,7 +848,7 @@ class queue } include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); - $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], htmlspecialchars_decode($config['jab_password']), $config['jab_use_ssl']); + $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], htmlspecialchars_decode($config['jab_password']), $config['jab_use_ssl'], $config['jab_verify_peer'], $config['jab_verify_peer_name'], $config['jab_allow_self_signed']); if (!$this->jabber->connect()) { @@ -1089,7 +1119,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) $options['ssl'] = array('verify_peer' => $verify_peer, 'verify_peer_name' => $verify_peer_name, 'allow_self_signed' => $allow_self_signed); $socket_context = stream_context_create($options); - $smtp->socket = stream_socket_client($remote_socket, $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $socket_context); + $smtp->socket = @stream_socket_client($remote_socket, $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $socket_context); $collector->uninstall(); $error_contents = $collector->format_errors(); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 7bc9608536..92679f8503 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1165,7 +1165,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id */ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '') { - global $db, $user, $phpbb_container; + global $db, $user, $phpbb_container, $phpbb_dispatcher; global $config, $phpEx, $phpbb_root_path; // Specify our post mode @@ -1416,6 +1416,34 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ sync('topic_reported', 'topic_id', array($topic_id)); } + /** + * This event is used for performing actions directly after a post or topic + * has been deleted. + * + * @event core.delete_post_after + * @var int forum_id Post forum ID + * @var int topic_id Post topic ID + * @var int post_id Post ID + * @var array data Post data + * @var bool is_soft Soft delete flag + * @var string softdelete_reason Soft delete reason + * @var string post_mode delete_topic, delete_first_post, delete_last_post or delete + * @var mixed next_post_id Next post ID in the topic (post ID or false) + * + * @since 3.1.11-RC1 + */ + $vars = array( + 'forum_id', + 'topic_id', + 'post_id', + 'data', + 'is_soft', + 'softdelete_reason', + 'post_mode', + 'next_post_id', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_post_after', compact($vars))); + return $next_post_id; } diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 971982e4fc..3d56bba21c 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -637,10 +637,13 @@ function mcp_move_topic($topic_ids) * * @event core.mcp_main_modify_shadow_sql * @var array shadow SQL array to be used by $db->sql_build_array + * @var array row Topic data * @since 3.1.11-RC1 + * @changed 3.1.11-RC1 Added variable: row */ $vars = array( 'shadow', + 'row', ); extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_shadow_sql', compact($vars))); @@ -1343,11 +1346,14 @@ function mcp_fork_topic($topic_ids) * Perform actions before forked topic is created. * * @event core.mcp_main_modify_fork_sql - * @var array sql_ary SQL array to be used by $db->sql_build_array + * @var array sql_ary SQL array to be used by $db->sql_build_array + * @var array topic_row Topic data * @since 3.1.11-RC1 + * @changed 3.1.11-RC1 Added variable: topic_row */ $vars = array( 'sql_ary', + 'topic_row', ); extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_fork_sql', compact($vars))); diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 7fa6ef4fff..dd7aebdbd1 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -26,7 +26,7 @@ function mcp_post_details($id, $mode, $action) { global $phpEx, $phpbb_root_path, $config, $request; global $template, $db, $user, $auth; - global $phpbb_dispatcher; + global $phpbb_container, $phpbb_dispatcher; $user->add_lang('posting'); @@ -352,7 +352,11 @@ function mcp_post_details($id, $mode, $action) // Get IP if ($auth->acl_get('m_info', $post_info['forum_id'])) { + /** @var \phpbb\pagination $pagination */ + $pagination = $phpbb_container->get('pagination'); + $rdns_ip_num = $request->variable('rdns', ''); + $start_users = $request->variable('start_users', 0); if ($rdns_ip_num != 'all') { @@ -361,23 +365,46 @@ function mcp_post_details($id, $mode, $action) ); } + $num_users = false; + if ($start_users) + { + $num_users = phpbb_get_num_posters_for_ip($db, $post_info['poster_ip']); + $start_users = $pagination->validate_start($start_users, $config['posts_per_page'], $num_users); + } + // Get other users who've posted under this IP $sql = 'SELECT poster_id, COUNT(poster_id) as postings FROM ' . POSTS_TABLE . " WHERE poster_ip = '" . $db->sql_escape($post_info['poster_ip']) . "' + AND poster_id <> " . (int) $post_info['poster_id'] . " GROUP BY poster_id - ORDER BY postings DESC"; - $result = $db->sql_query($sql); + ORDER BY postings DESC, poster_id ASC"; + $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start_users); + $page_users = 0; while ($row = $db->sql_fetchrow($result)) { - // Fill the user select list with users who have posted under this IP - if ($row['poster_id'] != $post_info['poster_id']) + $page_users++; + $users_ary[$row['poster_id']] = $row; + } + $db->sql_freeresult($result); + + if ($page_users == $config['posts_per_page'] || $start_users) + { + if ($num_users === false) { - $users_ary[$row['poster_id']] = $row; + $num_users = phpbb_get_num_posters_for_ip($db, $post_info['poster_ip']); } + + $pagination->generate_template_pagination( + $url . '&i=main&mode=post_details', + 'pagination', + 'start_users', + $num_users, + $config['posts_per_page'], + $start_users + ); } - $db->sql_freeresult($result); if (sizeof($users_ary)) { @@ -412,16 +439,26 @@ function mcp_post_details($id, $mode, $action) // A compound index on poster_id, poster_ip (posts table) would help speed up this query a lot, // but the extra size is only valuable if there are persons having more than a thousands posts. // This is better left to the really really big forums. + $start_ips = $request->variable('start_ips', 0); + + $num_ips = false; + if ($start_ips) + { + $num_ips = phpbb_get_num_ips_for_poster($db, $post_info['poster_id']); + $start_ips = $pagination->validate_start($start_ips, $config['posts_per_page'], $num_ips); + } $sql = 'SELECT poster_ip, COUNT(poster_ip) AS postings FROM ' . POSTS_TABLE . ' WHERE poster_id = ' . $post_info['poster_id'] . " GROUP BY poster_ip - ORDER BY postings DESC"; - $result = $db->sql_query($sql); + ORDER BY postings DESC, poster_ip ASC"; + $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start_ips); + $page_ips = 0; while ($row = $db->sql_fetchrow($result)) { + $page_ips++; $hostname = (($rdns_ip_num == $row['poster_ip'] || $rdns_ip_num == 'all') && $row['poster_ip']) ? @gethostbyaddr($row['poster_ip']) : ''; $template->assign_block_vars('iprow', array( @@ -436,6 +473,23 @@ function mcp_post_details($id, $mode, $action) } $db->sql_freeresult($result); + if ($page_ips == $config['posts_per_page'] || $start_ips) + { + if ($num_ips === false) + { + $num_ips = phpbb_get_num_ips_for_poster($db, $post_info['poster_id']); + } + + $pagination->generate_template_pagination( + $url . '&i=main&mode=post_details', + 'pagination_ips', + 'start_ips', + $num_ips, + $config['posts_per_page'], + $start_ips + ); + } + $user_select = ''; if (sizeof($usernames_ary)) @@ -454,6 +508,44 @@ function mcp_post_details($id, $mode, $action) } /** + * Get the number of posters for a given ip + * + * @param \phpbb\db\driver\driver_interface $db DBAL interface + * @param string $poster_ip IP + * @return int Number of posters + */ +function phpbb_get_num_posters_for_ip(\phpbb\db\driver\driver_interface $db, $poster_ip) +{ + $sql = 'SELECT COUNT(DISTINCT poster_id) as num_users + FROM ' . POSTS_TABLE . " + WHERE poster_ip = '" . $db->sql_escape($poster_ip) . "'"; + $result = $db->sql_query($sql); + $num_users = (int) $db->sql_fetchfield('num_users'); + $db->sql_freeresult($result); + + return $num_users; +} + +/** + * Get the number of ips for a given poster + * + * @param \phpbb\db\driver\driver_interface $db + * @param int $poster_id Poster user ID + * @return int Number of IPs for given poster + */ +function phpbb_get_num_ips_for_poster(\phpbb\db\driver\driver_interface $db, $poster_id) +{ + $sql = 'SELECT COUNT(DISTINCT poster_ip) as num_ips + FROM ' . POSTS_TABLE . ' + WHERE poster_id = ' . (int) $poster_id; + $result = $db->sql_query($sql); + $num_ips = (int) $db->sql_fetchfield('num_ips'); + $db->sql_freeresult($result); + + return $num_ips; +} + +/** * Change a post's poster */ function change_poster(&$post_info, $userdata) diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 06f76aa01a..86cdb090c8 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -449,6 +449,17 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $message_attachment = 0; $message_text = $message_subject = ''; + /** + * Predefine message text and subject + * + * @event core.ucp_pm_compose_predefined_message + * @var string message_text Message text + * @var string message_subject Messate subject + * @since 3.1.11-RC1 + */ + $vars = array('message_text', 'message_subject'); + extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_predefined_message', compact($vars))); + if ($to_user_id && $to_user_id != ANONYMOUS && $action == 'post') { $address_list['u'][$to_user_id] = 'to'; diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 4b9a50c05e..4db8a02405 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -602,20 +602,26 @@ $lang = array_merge($lang, array( $lang = array_merge($lang, array( 'ACP_JABBER_SETTINGS_EXPLAIN' => 'Here you can enable and control the use of Jabber for instant messaging and board notifications. Jabber is an open source protocol and therefore available for use by anyone. Some Jabber servers include gateways or transports which allow you to contact users on other networks. Not all servers offer all transports and changes in protocols can prevent transports from operating. Please be sure to enter already registered account details - phpBB will use the details you enter here as is.', - 'JAB_ENABLE' => 'Enable Jabber', - 'JAB_ENABLE_EXPLAIN' => 'Enables use of Jabber messaging and notifications.', - 'JAB_GTALK_NOTE' => 'Please note that GTalk will not work because the <samp>dns_get_record</samp> function could not be found. This function is not available in PHP4, and is not implemented on Windows platforms. It currently does not work on BSD-based systems, including Mac OS.', - 'JAB_PACKAGE_SIZE' => 'Jabber package size', - 'JAB_PACKAGE_SIZE_EXPLAIN' => 'This is the number of messages sent in one package. If set to 0 the message is sent immediately and will not be queued for later sending.', - 'JAB_PASSWORD' => 'Jabber password', - 'JAB_PASSWORD_EXPLAIN' => '<em><strong>Warning:</strong> This password will be stored as plain text in the database, visible to everybody who can access your database or who can view this configuration page.</em>', - 'JAB_PORT' => 'Jabber port', - 'JAB_PORT_EXPLAIN' => 'Leave blank unless you know it is not port 5222.', - 'JAB_SERVER' => 'Jabber server', - 'JAB_SERVER_EXPLAIN' => 'See %sjabber.org%s for a list of servers.', - 'JAB_SETTINGS_CHANGED' => 'Jabber settings changed successfully.', - 'JAB_USE_SSL' => 'Use SSL to connect', - 'JAB_USE_SSL_EXPLAIN' => 'If enabled a secure connection is tried to be established. The Jabber port will be modified to 5223 if port 5222 is specified.', - 'JAB_USERNAME' => 'Jabber username or JID', - 'JAB_USERNAME_EXPLAIN' => 'Specify a registered username or a valid JID. The username will not be checked for validity. If you only specify a username, then your JID will be the username and the server you specified above. Else, specify a valid JID, for example user@jabber.org.', + 'JAB_ALLOW_SELF_SIGNED' => 'Allow self-signed SSL certificates', + 'JAB_ALLOW_SELF_SIGNED_EXPLAIN' => 'Allow connections to Jabber server with self-signed SSL certificate.<em><strong>Warning:</strong> Allowing self-signed SSL certificates may cause security implications.</em>', + 'JAB_ENABLE' => 'Enable Jabber', + 'JAB_ENABLE_EXPLAIN' => 'Enables use of Jabber messaging and notifications.', + 'JAB_GTALK_NOTE' => 'Please note that GTalk will not work because the <samp>dns_get_record</samp> function could not be found. This function is not available in PHP4, and is not implemented on Windows platforms. It currently does not work on BSD-based systems, including Mac OS.', + 'JAB_PACKAGE_SIZE' => 'Jabber package size', + 'JAB_PACKAGE_SIZE_EXPLAIN' => 'This is the number of messages sent in one package. If set to 0 the message is sent immediately and will not be queued for later sending.', + 'JAB_PASSWORD' => 'Jabber password', + 'JAB_PASSWORD_EXPLAIN' => '<em><strong>Warning:</strong> This password will be stored as plain text in the database, visible to everybody who can access your database or who can view this configuration page.</em>', + 'JAB_PORT' => 'Jabber port', + 'JAB_PORT_EXPLAIN' => 'Leave blank unless you know it is not port 5222.', + 'JAB_SERVER' => 'Jabber server', + 'JAB_SERVER_EXPLAIN' => 'See %sjabber.org%s for a list of servers.', + 'JAB_SETTINGS_CHANGED' => 'Jabber settings changed successfully.', + 'JAB_USE_SSL' => 'Use SSL to connect', + 'JAB_USE_SSL_EXPLAIN' => 'If enabled a secure connection is tried to be established. The Jabber port will be modified to 5223 if port 5222 is specified.', + 'JAB_USERNAME' => 'Jabber username or JID', + 'JAB_USERNAME_EXPLAIN' => 'Specify a registered username or a valid JID. The username will not be checked for validity. If you only specify a username, then your JID will be the username and the server you specified above. Else, specify a valid JID, for example user@jabber.org.', + 'JAB_VERIFY_PEER' => 'Verify SSL certificate', + 'JAB_VERIFY_PEER_EXPLAIN' => 'Require verification of SSL certificate used by Jabber server.<em><strong>Warning:</strong> Connecting peers with unverified SSL certificates may cause security implications.</em>', + 'JAB_VERIFY_PEER_NAME' => 'Verify Jabber peer name', + 'JAB_VERIFY_PEER_NAME_EXPLAIN' => 'Require verification of peer name for Jabber servers using SSL / TLS connections.<em><strong>Warning:</strong> Connecting to unverified peers may cause security implications.</em>', )); diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 9be3cc9676..63235c01d8 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -367,7 +367,7 @@ $lang = array_merge($lang, array( 'AVATAR_DIR_SIZE' => 'Avatar directory size', 'BOARD_STARTED' => 'Board started', - 'BOARD_VERSION' => 'phpBB', + 'BOARD_VERSION' => 'Board version', 'DATABASE_SERVER_INFO' => 'Database server', 'DATABASE_SIZE' => 'Database size', @@ -395,7 +395,7 @@ $lang = array_merge($lang, array( 'NUMBER_USERS' => 'Number of users', 'NUMBER_ORPHAN' => 'Orphan attachments', - 'PHP_VERSION' => 'PHP', + 'PHP_VERSION' => 'PHP version', 'PHP_VERSION_OLD' => 'The version of PHP on this server (%1$s) will no longer be supported by future versions of phpBB. The minimum required version will be PHP %2$s. %3$sDetails%4$s', 'POSTS_PER_DAY' => 'Posts per day', @@ -430,10 +430,6 @@ $lang = array_merge($lang, array( 'RESYNC_STATS_SUCCESS' => 'Resynchronised statistics', 'RUN' => 'Run now', - 'SOFTWARE_HEADING' => 'Installed software', - 'SOFTWARE_PRODUCT' => 'Product', - 'SOFTWARE_VERSION' => 'Version', - 'STATISTIC' => 'Statistic', 'STATISTIC_RESYNC_OPTIONS' => 'Resynchronise or reset statistics', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index c2e741c6a7..1ee2fa525c 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -83,7 +83,7 @@ $lang = array_merge($lang, array( 'ACP_LINK' => 'Take me to <a href="%1$s">the ACP</a>', 'INSTALL_PHPBB_INSTALLED' => 'phpBB is already installed.', - 'INSTALL_PHPBB_NOT_INSTALLED' => 'phpBB is not installed yet.' + 'INSTALL_PHPBB_NOT_INSTALLED' => 'phpBB is not installed yet.', )); // Requirements translation @@ -119,7 +119,7 @@ $lang = array_merge($lang, array( 'RETEST_REQUIREMENTS' => 'Retest requirements', - 'STAGE_REQUIREMENTS' => 'Check requirements' + 'STAGE_REQUIREMENTS' => 'Check requirements', )); // General error messages diff --git a/phpBB/phpbb/db/migration/data/v31x/add_jabber_ssl_context_config_options.php b/phpBB/phpbb/db/migration/data/v31x/add_jabber_ssl_context_config_options.php new file mode 100644 index 0000000000..9f416fe069 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/add_jabber_ssl_context_config_options.php @@ -0,0 +1,32 @@ +<?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\db\migration\data\v31x; + +class add_jabber_ssl_context_config_options extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v31x\v3110'); + } + + public function update_data() + { + return array( + // See http://php.net/manual/en/context.ssl.php + array('config.add', array('jab_verify_peer', 1)), + array('config.add', array('jab_verify_peer_name', 1)), + array('config.add', array('jab_allow_self_signed', 0)), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v31x/add_latest_topics_index.php b/phpBB/phpbb/db/migration/data/v31x/add_latest_topics_index.php new file mode 100644 index 0000000000..fa2899e348 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/add_latest_topics_index.php @@ -0,0 +1,51 @@ +<?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\db\migration\data\v31x; + +class add_latest_topics_index extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v3110', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'topics' => array( + 'latest_topics' => array( + 'forum_id', + 'topic_last_post_time', + 'topic_last_post_id', + 'topic_moved_id', + ), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'topics' => array( + 'latest_topics', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p1.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p1.php new file mode 100644 index 0000000000..93ff31ec6c --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p1.php @@ -0,0 +1,46 @@ +<?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\db\migration\data\v32x; + +class user_notifications_table_index_p1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\cookie_notice_p2', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'user_id' => array('user_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'user_id', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p2.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p2.php new file mode 100644 index 0000000000..0a471766a0 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p2.php @@ -0,0 +1,46 @@ +<?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\db\migration\data\v32x; + +class user_notifications_table_index_p2 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_index_p1', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'uid_itm_id' => array('user_id', 'item_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'uid_itm_id', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p3.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p3.php new file mode 100644 index 0000000000..1636b3024a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_index_p3.php @@ -0,0 +1,46 @@ +<?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\db\migration\data\v32x; + +class user_notifications_table_index_p3 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_index_p2', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'usr_itm_tpe' => array('user_id', 'item_type', 'item_id'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'usr_itm_tpe', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_reduce_column_sizes.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_reduce_column_sizes.php new file mode 100644 index 0000000000..e0a107782e --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_reduce_column_sizes.php @@ -0,0 +1,48 @@ +<?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\db\migration\data\v32x; + +class user_notifications_table_reduce_column_sizes extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_index_p3', + ); + } + + public function update_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'user_notifications' => array( + 'item_type' => array('VCHAR:165', ''), + 'method' => array('VCHAR:165', ''), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'user_notifications' => array( + 'item_type' => array('VCHAR:255', ''), + 'method' => array('VCHAR:255', ''), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php new file mode 100644 index 0000000000..50d0642056 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_remove_duplicates.php @@ -0,0 +1,55 @@ +<?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\db\migration\data\v32x; + +class user_notifications_table_remove_duplicates extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_temp_index', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'remove_duplicates'))), + ); + } + + public function remove_duplicates() + { + $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->table_prefix . 'user_notifications'); + + $sql = "SELECT item_type, item_id, user_id, method, MAX(notify) AS notify + FROM {$this->table_prefix}user_notifications + GROUP BY item_type, item_id, user_id, method + HAVING COUNT(item_type) > 1"; + + $result = $this->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + // Delete the duplicate entries + $this->sql_query("DELETE FROM {$this->table_prefix}user_notifications + WHERE user_id = {$row['user_id']} + AND item_type = '{$row['item_type']}' + AND method = '{$row['method']}'"); + + // And re-insert as a single one + $insert_buffer->insert($row); + } + $this->db->sql_freeresult($result); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_temp_index.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_temp_index.php new file mode 100644 index 0000000000..80256a0e0a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_temp_index.php @@ -0,0 +1,46 @@ +<?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\db\migration\data\v32x; + +class user_notifications_table_temp_index extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_reduce_column_sizes', + ); + } + + public function update_schema() + { + return array( + 'add_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd' => array('item_type', 'item_id', 'user_id', 'method'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php new file mode 100644 index 0000000000..51cf90c8a0 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/user_notifications_table_unique_index.php @@ -0,0 +1,51 @@ +<?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\db\migration\data\v32x; + +class user_notifications_table_unique_index extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\user_notifications_table_remove_duplicates', + ); + } + + public function update_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd', + ), + ), + 'add_unique_index' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd' => array('item_type', 'item_id', 'user_id', 'method'), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'drop_keys' => array( + $this->table_prefix . 'user_notifications' => array( + 'itm_usr_mthd', + ), + ), + ); + } +} diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index 9273d69cd6..76036554d2 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -946,7 +946,20 @@ class tools implements tools_interface { case 'oracle': case 'sqlite3': - $row[$col] = substr($row[$col], strlen($table_name) + 1); + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name, false); + $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) + + if (strpos($index_name , $table_name) === false) + { + if (strpos($index_name, $table_prefix) !== false) + { + $row[$col] = substr($row[$col], strlen($table_prefix) + 1); + } + else + { + $row[$col] = substr($row[$col], strlen($table_name) + 1); + } + } break; } @@ -1359,12 +1372,14 @@ class tools implements tools_interface { case 'mysql_40': case 'mysql_41': + $index_name = $this->check_index_name_length($table_name, $index_name, false); $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; break; case 'oracle': case 'sqlite3': - $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name, false); + $statements[] = 'DROP INDEX ' . $index_name; break; } @@ -1487,17 +1502,17 @@ class tools implements tools_interface { $statements = array(); - $this->check_index_name_length($table_name, $index_name); - switch ($this->sql_layer) { case 'oracle': case 'sqlite3': - $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name); + $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; break; case 'mysql_40': case 'mysql_41': + $index_name = $this->check_index_name_length($table_name, $index_name); $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; break; } @@ -1512,8 +1527,6 @@ class tools implements tools_interface { $statements = array(); - $this->check_index_name_length($table_name, $index_name); - // remove index length unless MySQL4 if ('mysql_40' != $this->sql_layer) { @@ -1524,7 +1537,8 @@ class tools implements tools_interface { case 'oracle': case 'sqlite3': - $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name); + $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; break; case 'mysql_40': @@ -1539,6 +1553,7 @@ class tools implements tools_interface } // no break case 'mysql_41': + $index_name = $this->check_index_name_length($table_name, $index_name); $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')'; break; } @@ -1551,15 +1566,35 @@ class tools implements tools_interface * * @param string $table_name * @param string $index_name + * @param bool $throw_error + * @return string The index name, shortened if too long */ - protected function check_index_name_length($table_name, $index_name) + protected function check_index_name_length($table_name, $index_name, $throw_error = true) { - $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) - if (strlen($table_name . $index_name) - strlen($table_prefix) > 24) + if (strlen($index_name) > 30) { - $max_length = strlen($table_prefix) + 24; - trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR); + // Try removing the table prefix if it's at the beginning + $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) + if (strpos($index_name, $table_prefix) === 0) + { + $index_name = substr($index_name, strlen($table_prefix) + 1); + return $this->check_index_name_length($table_name, $index_name); + } + + // Try removing the table name then + if (strpos($index_name, $table_name) === 0) + { + $index_name = substr($index_name, strlen($table_name) + 1); + return $this->check_index_name_length($table_name, $index_name); + } + + if ($throw_error) + { + trigger_error("Index name '$index_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR); + } } + + return $index_name; } /** diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 00aa2c6826..4b4109bd85 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -262,8 +262,8 @@ class manager */ public function disable_step($name) { - // ignore extensions that are already disabled - if ($this->is_disabled($name)) + // ignore extensions that are not enabled + if (!$this->is_enabled($name)) { return false; } diff --git a/phpBB/phpbb/help/controller/help.php b/phpBB/phpbb/help/controller/help.php index 9cc3b0c8b4..3bf6fe3098 100644 --- a/phpBB/phpbb/help/controller/help.php +++ b/phpBB/phpbb/help/controller/help.php @@ -64,6 +64,7 @@ class help */ public function handle($mode) { + $template_file = 'faq_body.html'; switch ($mode) { case 'faq': @@ -85,13 +86,16 @@ class help * @var string lang_file Language file containing the help data * @var string ext_name Vendor and extension name where the help * language file can be loaded from + * @var string template_file Template file name * @since 3.1.4-RC1 + * @changed 3.1.11-RC1 Added template_file var */ $vars = array( 'page_title', 'mode', 'lang_file', 'ext_name', + 'template_file', ); extract($this->dispatcher->trigger_event('core.faq_mode_validation', compact($vars))); @@ -113,7 +117,7 @@ class help $this->assign_to_template($this->user->help); make_jumpbox(append_sid("{$this->root_path}viewforum.{$this->php_ext}")); - return $this->helper->render('faq_body.html', $page_title); + return $this->helper->render($template_file, $page_title); } /** diff --git a/phpBB/phpbb/template/base.php b/phpBB/phpbb/template/base.php index 41c0a01ba8..d502aceab8 100644 --- a/phpBB/phpbb/template/base.php +++ b/phpBB/phpbb/template/base.php @@ -107,6 +107,27 @@ abstract class base implements template /** * {@inheritdoc} */ + public function retrieve_vars(array $vararray) + { + $result = array(); + foreach ($vararray as $varname) + { + $result[$varname] = $this->retrieve_var($varname); + } + return $result; + } + + /** + * {@inheritdoc} + */ + public function retrieve_var($varname) + { + return $this->context->retrieve_var($varname); + } + + /** + * {@inheritdoc} + */ public function assign_block_vars($blockname, array $vararray) { $this->context->assign_block_vars($blockname, $vararray); @@ -127,6 +148,14 @@ abstract class base implements template /** * {@inheritdoc} */ + public function retrieve_block_vars($blockname, array $vararray) + { + return $this->context->retrieve_block_vars($blockname, $vararray); + } + + /** + * {@inheritdoc} + */ public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') { return $this->context->alter_block_array($blockname, $vararray, $key, $mode); diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 5e4f71a2a9..392efd5933 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -87,6 +87,17 @@ class context } /** + * Retreive a single scalar value from a single key. + * + * @param string $varname Variable name + * @return mixed Variable value, or null if not set + */ + public function retrieve_var($varname) + { + return isset($this->rootref[$varname]) ? $this->rootref[$varname] : null; + } + + /** * Returns a reference to template data array. * * This function is public so that template renderer may invoke it. @@ -264,6 +275,68 @@ class context } /** + * Retrieve key variable pairs from the specified block + * + * @param string $blockname Name of block to retrieve $vararray from + * @param array $vararray An array of variable names, empty array retrieves all vars + * @return array of hashes with variable name as key and retrieved value or null as value + */ + public function retrieve_block_vars($blockname, array $vararray) + { + // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 + $blocks = explode('.', $blockname); + $blockcount = sizeof($blocks) - 1; + + $block = $this->tpldata; + for ($i = 0; $i <= $blockcount; $i++) + { + if (($pos = strpos($blocks[$i], '[')) !== false) + { + $name = substr($blocks[$i], 0, $pos); + + if (strpos($blocks[$i], '[]') === $pos) + { + $index = sizeof($block[$name]) - 1; + } + else + { + $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); + } + } + else + { + $name = $blocks[$i]; + $index = sizeof($block[$name]) - 1; + } + $block = $block[$name]; + $block = $block[$index]; + } + + $result = array(); + if ($vararray === array()) + { + // The calculated vars that depend on the block position are excluded from the complete block returned results + $excluded_vars = array('S_FIRST_ROW', 'S_LAST_ROW', 'S_BLOCK_NAME', 'S_NUM_ROWS', 'S_ROW_COUNT', 'S_ROW_NUM'); + + foreach ($block as $varname => $varvalue) + { + if ($varname === strtoupper($varname) && !is_array($varvalue) && !in_array($varname, $excluded_vars)) + { + $result[$varname] = $varvalue; + } + } + } + else + { + foreach ($vararray as $varname) + { + $result[$varname] = isset($block[$varname]) ? $block[$varname] : null; + } + } + return $result; + } + + /** * Find the index for a specified key in the innermost specified block * * @param string $blockname the blockname, for example 'loop' diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index d1ec442e9a..df83d5bc43 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -128,6 +128,22 @@ interface template public function append_var($varname, $varval); /** + * Retrieve multiple template values + * + * @param array $vararray An array with variable names + * @return array A hash of variable name => value pairs (value is null if not set) + */ + public function retrieve_vars(array $vararray); + + /** + * Retreive a single scalar value from a single key. + * + * @param string $varname Variable name + * @return mixed Variable value, or null if not set + */ + public function retrieve_var($varname); + + /** * Assign key variable pairs from an array to a specified block * @param string $blockname Name of block to assign $vararray to * @param array $vararray A hash of variable name => value pairs @@ -144,6 +160,14 @@ interface template public function assign_block_vars_array($blockname, array $block_vars_array); /** + * Retrieve variable values from an specified block + * @param string $blockname Name of block to retrieve $vararray from + * @param array $vararray An array with variable names, empty array gets all vars + * @return array A hash of variable name => value pairs (value is null if not set) + */ + public function retrieve_block_vars($blockname, array $vararray); + + /** * Change already assigned key variable pair (one-dimensional - single loop entry) * * An example of how to use this function: diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js index 1bb3aabb9b..6903ad2261 100644 --- a/phpBB/styles/prosilver/template/ajax.js +++ b/phpBB/styles/prosilver/template/ajax.js @@ -26,7 +26,7 @@ phpbb.addAjaxCallback('mark_forums_read', function(res) { }); // Mark subforums read - $('a.subforum[class*="unread"]').removeClass('unread').addClass('read'); + $('a.subforum[class*="unread"]').removeClass('unread').addClass('read').children('.icon.icon-red').removeClass('icon-red').addClass('icon-blue'); // Mark topics read if we are watching a category and showing active topics if ($('#active_topics').length) { diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index 4ab6de250f..621e226260 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -52,8 +52,8 @@ <!-- EVENT forumlist_body_subforums_before --> <br /><strong>{forumrow.L_SUBFORUM_STR}{L_COLON}</strong> <!-- BEGIN subforum --> - <a href="{forumrow.subforum.U_SUBFORUM}" class="subforum<!-- IF forumrow.subforum.S_UNREAD --> unread<!-- ELSE --> read<!-- ENDIF -->" title="<!-- IF forumrow.subforum.S_UNREAD -->{L_UNREAD_POSTS}<!-- ELSE -->{L_NO_UNREAD_POSTS}<!-- ENDIF -->"> - <i class="icon <!-- IF forumrow.subforum.IS_LINK -->fa-external-link<!-- ELSE -->fa-file-o<!-- ENDIF --> fa-fw <!-- IF forumrow.subforum.S_UNREAD --> icon-red<!-- ELSE --> icon-blue<!-- ENDIF --> icon-md" aria-hidden="true"></i>{forumrow.subforum.SUBFORUM_NAME}</a><!-- IF not forumrow.subforum.S_LAST_ROW -->{L_COMMA_SEPARATOR}<!-- ENDIF --> + <!-- EVENT forumlist_body_subforum_link_prepend --><a href="{forumrow.subforum.U_SUBFORUM}" class="subforum<!-- IF forumrow.subforum.S_UNREAD --> unread<!-- ELSE --> read<!-- ENDIF -->" title="<!-- IF forumrow.subforum.S_UNREAD -->{L_UNREAD_POSTS}<!-- ELSE -->{L_NO_UNREAD_POSTS}<!-- ENDIF -->"> + <i class="icon <!-- IF forumrow.subforum.IS_LINK -->fa-external-link<!-- ELSE -->fa-file-o<!-- ENDIF --> fa-fw <!-- IF forumrow.subforum.S_UNREAD --> icon-red<!-- ELSE --> icon-blue<!-- ENDIF --> icon-md" aria-hidden="true"></i>{forumrow.subforum.SUBFORUM_NAME}</a><!-- IF not forumrow.subforum.S_LAST_ROW -->{L_COMMA_SEPARATOR}<!-- ENDIF --><!-- EVENT forumlist_body_subforum_link_append --> <!-- END subforum --> <!-- EVENT forumlist_body_subforums_after --> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/index_body.html b/phpBB/styles/prosilver/template/index_body.html index ec5bf35476..b292c40eb2 100644 --- a/phpBB/styles/prosilver/template/index_body.html +++ b/phpBB/styles/prosilver/template/index_body.html @@ -40,13 +40,18 @@ <!-- IF U_VIEWONLINE --><h3><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a></h3><!-- ELSE --><h3>{L_WHO_IS_ONLINE}</h3><!-- ENDIF --> <p> <!-- EVENT index_body_block_online_prepend --> - {TOTAL_USERS_ONLINE} ({L_ONLINE_EXPLAIN})<br />{RECORD_USERS}<br /> <br />{LOGGED_IN_USER_LIST} - <!-- IF LEGEND --><br /><em>{L_LEGEND}{L_COLON} {LEGEND}</em><!-- ENDIF --> + {TOTAL_USERS_ONLINE} ({L_ONLINE_EXPLAIN})<br />{RECORD_USERS}<br /> + <!-- IF U_VIEWONLINE --> + <br />{LOGGED_IN_USER_LIST} + <!-- IF LEGEND --><br /><em>{L_LEGEND}{L_COLON} {LEGEND}</em><!-- ENDIF --> + <!-- ENDIF --> <!-- EVENT index_body_block_online_append --> </p> </div> <!-- ENDIF --> +<!-- EVENT index_body_birthday_block_before --> + <!-- IF S_DISPLAY_BIRTHDAY_LIST --> <div class="stat-block birthday-list"> <h3>{L_BIRTHDAYS}</h3> diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html index a0de554e21..af16c8ab84 100644 --- a/phpBB/styles/prosilver/template/mcp_post.html +++ b/phpBB/styles/prosilver/template/mcp_post.html @@ -294,6 +294,14 @@ </tbody> </table> + <div class="pagination"> + <!-- INCLUDE pagination.html --> + </div> + </div> + </div> + + <div class="panel"> + <div class="inner"> <table class="table1"> <thead> <tr> @@ -315,7 +323,27 @@ </tbody> </table> - <p><a href="{U_LOOKUP_ALL}#ip">{L_LOOKUP_ALL}</a></p> + <div class="buttons"> + <p><a href="{U_LOOKUP_ALL}#ip">{L_LOOKUP_ALL}</a></p> + </div> + + <div class="pagination"> + <ul> + <!-- BEGIN pagination_ips --> + <!-- IF pagination_ips.S_IS_PREV --> + <li class="arrow previous"><a class="button button-icon-only" href="{pagination_ips.PAGE_URL}" rel="prev" role="button"><i class="icon fa-chevron-{S_CONTENT_FLOW_BEGIN} fa-fw" aria-hidden="true"></i><span class="sr-only">{L_PREVIOUS}</span></a></li> + <!-- ELSEIF pagination_ips.S_IS_CURRENT --> + <li class="active"><span>{pagination_ips.PAGE_NUMBER}</span></li> + <!-- ELSEIF pagination_ips.S_IS_ELLIPSIS --> + <li class="ellipsis" role="separator"><span>{L_ELLIPSIS}</span></li> + <!-- ELSEIF pagination_ips.S_IS_NEXT --> + <li class="arrow next"><a class="button button-icon-only" href="{pagination_ips.PAGE_URL}" rel="next" role="button"><i class="icon fa-chevron-{S_CONTENT_FLOW_END} fa-fw" aria-hidden="true"></i><span class="sr-only">{L_NEXT}</span></a></li> + <!-- ELSE --> + <li><a class="button" href="{pagination_ips.PAGE_URL}" role="button">{pagination_ips.PAGE_NUMBER}</a></li> + <!-- ENDIF --> + <!-- END pagination_ips --> + </ul> + </div> </div> </div> diff --git a/phpBB/styles/prosilver/template/mcp_topic.html b/phpBB/styles/prosilver/template/mcp_topic.html index d64c9c9a21..35b1ecca0a 100644 --- a/phpBB/styles/prosilver/template/mcp_topic.html +++ b/phpBB/styles/prosilver/template/mcp_topic.html @@ -111,7 +111,9 @@ </li> </ul> + <!-- EVENT mcp_topic_postrow_post_subject_before --> <h3><a href="{postrow.U_POST_DETAILS}">{postrow.POST_SUBJECT}</a></h3> + <!-- EVENT mcp_topic_postrow_post_subject_after --> <!-- EVENT mcp_topic_postrow_post_details_before --> <p class="author"> diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html index 6bbf9c9afe..997bc28b4b 100644 --- a/phpBB/styles/prosilver/template/search_results.html +++ b/phpBB/styles/prosilver/template/search_results.html @@ -185,6 +185,7 @@ <dd class="search-result-date">{searchresults.POST_DATE}</dd> <dd>{L_FORUM}{L_COLON} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a></dd> <dd>{L_TOPIC}{L_COLON} <a href="{searchresults.U_VIEW_TOPIC}">{searchresults.TOPIC_TITLE}</a></dd> + <!-- EVENT search_results_topic_title_after --> <dd>{L_REPLIES}{L_COLON} <strong>{searchresults.TOPIC_REPLIES}</strong></dd> <dd>{L_VIEWS}{L_COLON} <strong>{searchresults.TOPIC_VIEWS}</strong></dd> <!-- EVENT search_results_postprofile_after --> diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 867fd84112..b57f48ba15 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -289,9 +289,9 @@ <!-- INCLUDE jumpbox.html --> -<!-- IF S_DISPLAY_ONLINE_LIST --> +<!-- IF S_DISPLAY_ONLINE_LIST and U_VIEWONLINE --> <div class="stat-block online-list"> - <h3><!-- IF U_VIEWONLINE --><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a><!-- ELSE -->{L_WHO_IS_ONLINE}<!-- ENDIF --></h3> + <h3><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a></h3> <p>{LOGGED_IN_USER_LIST}</p> </div> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html index 522151cf7d..71d364bbb9 100644 --- a/phpBB/styles/prosilver/template/viewtopic_body.html +++ b/phpBB/styles/prosilver/template/viewtopic_body.html @@ -439,9 +439,9 @@ <!-- EVENT viewtopic_body_footer_before --> <!-- INCLUDE jumpbox.html --> -<!-- IF S_DISPLAY_ONLINE_LIST --> +<!-- IF S_DISPLAY_ONLINE_LIST and U_VIEWONLINE --> <div class="stat-block online-list"> - <h3><!-- IF U_VIEWONLINE --><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a><!-- ELSE -->{L_WHO_IS_ONLINE}<!-- ENDIF --></h3> + <h3><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a></h3> <p>{LOGGED_IN_USER_LIST}</p> </div> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 860c2f6cb4..70cfb83a78 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -501,7 +501,6 @@ li.breadcrumbs span:first-child > a { /* Quote block */ .rtl blockquote { margin: 0.5em 25px 0 1px; - background-position: 99% 8px; } .rtl blockquote blockquote { @@ -511,10 +510,13 @@ li.breadcrumbs span:first-child > a { .rtl blockquote cite { /* Username/source of quoter */ - margin-right: 20px; margin-left: 0; } +.rtl blockquote cite:before, .rtl .uncited:before { + padding-left: 5px; +} + .rtl blockquote .codebox { margin-right: 0; } diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index 35490c9338..ffaa71034f 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -409,14 +409,9 @@ dl.faq dt { /* Quote block */ blockquote { background-color: #EBEADD; - background-image: url("./images/quote.gif"); border-color:#DBDBCE; } -.rtl blockquote { - background-image: url("./images/quote_rtl.gif"); -} - blockquote blockquote { /* Nested quotes */ background-color:#EFEED9; diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 95168d1d97..741056e4c4 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -448,7 +448,6 @@ ul.searchresults { ----------------------------------------*/ /* Quote block */ blockquote { - background: transparent none 6px 8px no-repeat; border: 1px solid transparent; font-size: 0.95em; margin: 1em 1px 1em 25px; @@ -466,7 +465,6 @@ blockquote cite { /* Username/source of quoter */ font-style: normal; font-weight: bold; - margin-left: 20px; display: block; font-size: 0.9em; } @@ -475,8 +473,8 @@ blockquote cite cite { font-size: 1em; } -blockquote.uncited { - padding-top: 25px; +blockquote cite:before, .uncited:before { + padding-right: 5px; } blockquote cite > div { @@ -491,18 +489,17 @@ blockquote cite > div { /* Code block */ .codebox { - padding: 3px; border: 1px solid transparent; font-size: 1em; margin: 1em 0 1.2em 0; - overflow-x: scroll; word-wrap: normal; } .codebox p { text-transform: uppercase; border-bottom: 1px solid transparent; - margin-bottom: 3px; + margin-bottom: 0; + padding: 3px; font-size: 0.8em !important; font-weight: bold; display: block; @@ -517,10 +514,9 @@ blockquote .codebox { display: block; height: auto; max-height: 200px; - padding-top: 5px; + padding: 5px 3px; font: 0.9em Monaco, "Andale Mono","Courier New", Courier, monospace; line-height: 1.3em; - margin: 2px 0; } /* Attachments diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index 411fecaf3b..6643f12d06 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -9,7 +9,7 @@ * Just change the name of the font after the 14/1 to the name of * the font you wish to use. */ -.icon, .button .icon { +.icon, .button .icon, blockquote cite:before, .uncited:before { display: inline-block; font-weight: normal; font-style: normal; @@ -85,3 +85,12 @@ line-height: .9; height: 12px; } + +blockquote cite:before, .uncited:before { + content: '\f10d'; /* Font Awesome quote-left */ +} + +.rtl blockquote cite:before, .rtl .uncited:before { + content: '\f10e'; /* Font Awesome quote-right */ +} + diff --git a/tests/mcp/fixtures/post_ip.xml b/tests/mcp/fixtures/post_ip.xml new file mode 100644 index 0000000000..fad2193396 --- /dev/null +++ b/tests/mcp/fixtures/post_ip.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> + <table name="phpbb_posts"> + <column>post_id</column> + <column>poster_id</column> + <column>post_edit_user</column> + <column>post_delete_user</column> + <column>post_username</column> + <column>topic_id</column> + <column>forum_id</column> + <column>post_visibility</column> + <column>post_time</column> + <column>post_text</column> + <column>post_reported</column> + <column>poster_ip</column> + <row> + <value>1</value> + <value>2</value> + <value>2</value> + <value>2</value> + <value></value> + <value>1</value> + <value>1</value> + <value>1</value> + <value>1</value> + <value></value> + <value>1</value> + <value>127.0.0.1</value> + </row> + <row> + <value>2</value> + <value>1</value> + <value>1</value> + <value>1</value> + <value>Other</value> + <value>2</value> + <value>2</value> + <value>1</value> + <value>1</value> + <value></value> + <value>1</value> + <value>127.0.0.2</value> + </row> + <row> + <value>3</value> + <value>2</value> + <value>2</value> + <value>2</value> + <value></value> + <value>3</value> + <value>3</value> + <value>1</value> + <value>1</value> + <value></value> + <value>1</value> + <value>127.0.0.3</value> + </row> + <row> + <value>4</value> + <value>1</value> + <value>1</value> + <value>1</value> + <value>Other</value> + <value>4</value> + <value>4</value> + <value>1</value> + <value>1</value> + <value></value> + <value>1</value> + <value>127.0.0.1</value> + </row> + </table> +</dataset> diff --git a/tests/mcp/post_ip_test.php b/tests/mcp/post_ip_test.php new file mode 100644 index 0000000000..72a9f62774 --- /dev/null +++ b/tests/mcp/post_ip_test.php @@ -0,0 +1,67 @@ +<?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. + * + */ + +require_once dirname(__FILE__) . '/../../phpBB/includes/mcp/mcp_post.php'; + +class phpbb_mcp_post_ip_test extends phpbb_database_test_case +{ + /** @var \phpbb\db\driver\driver_interface */ + protected $db; + + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/post_ip.xml'); + } + + protected function setUp() + { + parent::setUp(); + + $this->db = $this->new_dbal(); + } + + public function data_get_num_ips() + { + return array( + array(2, 1), + array(2, 2), + array(0, 3), + ); + } + + /** + * @dataProvider data_get_num_ips + */ + public function test_get_num_ips($expected, $poster_id) + { + $this->assertSame($expected, phpbb_get_num_ips_for_poster($this->db, $poster_id)); + } + + public function data_get_num_posters() + { + return array( + array(2, '127.0.0.1'), + array(1, '127.0.0.2'), + array(1, '127.0.0.3'), + array(0, '127.0.0.4'), + ); + } + + /** + * @dataProvider data_get_num_posters + */ + public function test_get_num_posters($expected, $ip) + { + $this->assertSame($expected, phpbb_get_num_posters_for_ip($this->db, $ip)); + } +} diff --git a/tests/template/template_test.php b/tests/template/template_test.php index f86572cae8..9f2124418d 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -597,6 +597,37 @@ class phpbb_template_template_test extends phpbb_template_template_test_case $this->assertEquals($expecting, $this->display('append_var')); } + public function test_retrieve_data() + { + $this->template->set_filenames(array('test' => 'loop_nested.html')); + + $this->template->assign_var('TEST_MORE', false); + + // @todo Change this + $this->template->assign_vars(array('ONE' => true, 'TWO' => 'two', 'THREE' => 3)); + $this->template->assign_block_vars('outer', array('POSITION' => 'O1')); + $this->template->assign_block_vars('outer.middle', array('POSITION' => 'O1M1')); + $this->template->assign_block_vars('outer', array('POSITION' => 'O2')); + $this->template->assign_block_vars('outer.middle', array('POSITION' => 'O2M1')); + $this->template->assign_block_vars('outer.middle', array('POSITION' => 'O2M2')); + $this->template->assign_block_vars('outer', array('POSITION' => 'O3')); + $this->template->assign_block_vars('outer.middle', array('POSITION' => 'O3M1')); + $this->template->assign_block_vars('outer.middle', array('POSITION' => 'O3M2', 'ONE' => true, 'TWO' => 'two', 'THREE' => 3)); + $this->template->assign_block_vars('outer.middle', array('POSITION' => 'O3M3')); + + $expect = 'outer - 0middle - 0outer - 1middle - 0middle - 1outer - 2middle - 0middle - 1middle - 2'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring template is built correctly before modification'); + + $this->assertEquals(true, $this->template->retrieve_var('ONE'), 'Retrieve a single value from the template'); + $this->assertEquals(null, $this->template->retrieve_var('FOUR'), 'Retrieve a non_existent value from the template'); + $this->assertEquals(array('TWO' => 'two', 'THREE' => 3, 'FOUR' => null), $this->template->retrieve_vars(array('TWO','THREE', 'FOUR')), 'Retrieve several variables from the template'); + + $this->assertEquals(array('POSITION' => 'O3', 'SIZE' => null), $this->template->retrieve_block_vars('outer', array('POSITION', 'SIZE')), 'Retrieve vars from a block in the template'); + $this->assertEquals(array('POSITION' => 'O2M1'), $this->template->retrieve_block_vars('outer[1].middle[0]', array('POSITION')), 'Retrieve single var from a nested indexed block in the template'); + $this->assertEquals(array('S_ROW_NUM' => 2), $this->template->retrieve_block_vars('outer.middle', array('S_ROW_NUM')), 'Retrieve automatic var from a block in the template'); + $this->assertEquals(array('POSITION' => 'O3M2', 'ONE' => true, 'TWO' => 'two', 'THREE' => 3), $this->template->retrieve_block_vars('outer[2].middle[1]', array()), 'Retrieve all vars from a block in the template'); + } + public function test_php() { global $phpbb_root_path; diff --git a/tests/text_processing/generate_text_for_display_test.php b/tests/text_processing/generate_text_for_display_test.php index b8b5b18561..9c7152a008 100644 --- a/tests/text_processing/generate_text_for_display_test.php +++ b/tests/text_processing/generate_text_for_display_test.php @@ -100,7 +100,7 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca $renderer->set_viewcensors(false); $this->assertSame('apple', $renderer->render($original)); - $this->assertSame('banana', generate_text_for_display($original, '', '', 0, truee)); + $this->assertSame('banana', generate_text_for_display($original, '', '', 0, true)); $this->assertSame('apple', $renderer->render($original), 'The original setting was not restored'); } |