Merge branch 'develop' of https://github.com/phpbb/phpbb3 into ticket/11465

This commit is contained in:
Marc Alexander 2013-05-12 22:41:00 +02:00
commit 7e70eec5a3
185 changed files with 6817 additions and 2004 deletions

View file

@ -9,26 +9,19 @@ env:
- DB=mysql - DB=mysql
- DB=postgres - DB=postgres
matrix:
allow_failures:
- php: 5.5
before_script: before_script:
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi" - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi" - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi" - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi"
- travis/install-php-extensions.sh - travis/install-php-extensions.sh
- pyrus set auto_discover 1
- pyrus install --force phpunit/DbUnit
- phpenv rehash
- cd phpBB - cd phpBB
- php ../composer.phar install --dev - php ../composer.phar install --dev
- cd .. - cd ..
- sh -c "if [ `php -r "echo (int) version_compare(PHP_VERSION, '5.3.19', '>=');"` = "1" ]; then travis/setup-webserver.sh; fi" - sh -c "if [ `php -r "echo (int) version_compare(PHP_VERSION, '5.3.19', '>=');"` = "1" ]; then travis/setup-webserver.sh; fi"
script: script:
- phpunit --configuration travis/phpunit-$DB-travis.xml - phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml
notifications: notifications:
email: email:
recipients: recipients:

View file

@ -56,7 +56,8 @@
<target name="test" depends="clean,prepare,composer"> <target name="test" depends="clean,prepare,composer">
<exec dir="." <exec dir="."
command="phpunit --log-junit build/logs/phpunit.xml command="phpBB/vendor/bin/phpunit
--log-junit build/logs/phpunit.xml
--coverage-clover build/logs/clover.xml --coverage-clover build/logs/clover.xml
--coverage-html build/coverage" --coverage-html build/coverage"
passthru="true" /> passthru="true" />
@ -64,7 +65,8 @@
<target name="test-slow" depends="clean,prepare,composer"> <target name="test-slow" depends="clean,prepare,composer">
<exec dir="." <exec dir="."
command="phpunit --log-junit build/logs/phpunit.xml command="phpBB/vendor/bin/phpunit
--log-junit build/logs/phpunit.xml
--configuration phpunit.xml.all --configuration phpunit.xml.all
--group slow --group slow
--coverage-clover build/logs/clover-slow.xml --coverage-clover build/logs/clover-slow.xml

Binary file not shown.

View file

@ -78,12 +78,12 @@ function work($pull_id, $remote)
add_remote($pull_user, 'phpbb3'); add_remote($pull_user, 'phpbb3');
run("git fetch $pull_user"); run("git fetch $pull_user");
run("git merge --no-ff $pull_user/$pull_branch"); run("git merge --no-ff $pull_user/$pull_branch");
run("phpunit"); run("phpBB/vendor/bin/phpunit");
run("git checkout develop"); run("git checkout develop");
run("git pull $remote develop"); run("git pull $remote develop");
run("git merge --no-ff develop-olympus"); run("git merge --no-ff develop-olympus");
run("phpunit"); run("phpBB/vendor/bin/phpunit");
break; break;
case 'develop': case 'develop':
@ -93,7 +93,7 @@ function work($pull_id, $remote)
add_remote($pull_user, 'phpbb3'); add_remote($pull_user, 'phpbb3');
run("git fetch $pull_user"); run("git fetch $pull_user");
run("git merge --no-ff $pull_user/$pull_branch"); run("git merge --no-ff $pull_user/$pull_branch");
run("phpunit"); run("phpBB/vendor/bin/phpunit");
break; break;
default: default:

View file

@ -115,9 +115,9 @@ phpbb.addAjaxCallback('activate_deactivate', function(res) {
el.text(res.text); el.text(res.text);
if (newHref.indexOf('deactivate') !== -1) { if (newHref.indexOf('deactivate') !== -1) {
newHref = newHref.replace('deactivate', 'activate') newHref = newHref.replace('deactivate', 'activate');
} else { } else {
newHref = newHref.replace('activate', 'deactivate') newHref = newHref.replace('activate', 'deactivate');
} }
el.attr('href', newHref); el.attr('href', newHref);
@ -148,6 +148,12 @@ $('[data-ajax]').each(function() {
} }
}); });
/**
* Automatically resize textarea
*/
$(document).ready(function() {
phpbb.resizeTextArea($('textarea:not(.no-auto-resize)'), {minHeight: 75});
});
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

View file

@ -10,18 +10,16 @@ var theSelection = false;
// Check for Browser & Platform for PC & IE specific bits // Check for Browser & Platform for PC & IE specific bits
// More details from: http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html // More details from: http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
var clientPC = navigator.userAgent.toLowerCase(); // Get client info var clientPC = navigator.userAgent.toLowerCase(); // Get client info
var clientVer = parseInt(navigator.appVersion); // Get browser version var clientVer = parseInt(navigator.appVersion, 10); // Get browser version
var is_ie = ((clientPC.indexOf('msie') != -1) && (clientPC.indexOf('opera') == -1));
var is_win = ((clientPC.indexOf('win') != -1) || (clientPC.indexOf('16bit') != -1));
var is_ie = ((clientPC.indexOf('msie') !== -1) && (clientPC.indexOf('opera') === -1));
var is_win = ((clientPC.indexOf('win') !== -1) || (clientPC.indexOf('16bit') !== -1));
var baseHeight; var baseHeight;
/** /**
* Shows the help messages in the helpline window * Shows the help messages in the helpline window
*/ */
function helpline(help) function helpline(help) {
{
document.forms[form_name].helpbox.value = help_line[help]; document.forms[form_name].helpbox.value = help_line[help];
} }
@ -29,26 +27,22 @@ function helpline(help)
* Fix a bug involving the TextRange object. From * Fix a bug involving the TextRange object. From
* http://www.frostjedi.com/terra/scripts/demo/caretBug.html * http://www.frostjedi.com/terra/scripts/demo/caretBug.html
*/ */
function initInsertions() function initInsertions() {
{
var doc; var doc;
if(document.forms[form_name])
{ if (document.forms[form_name]) {
doc = document; doc = document;
} } else {
else
{
doc = opener.document; doc = opener.document;
} }
var textarea = doc.forms[form_name].elements[text_name]; var textarea = doc.forms[form_name].elements[text_name];
if (is_ie && typeof(baseHeight) != 'number')
{ if (is_ie && typeof(baseHeight) !== 'number') {
textarea.focus(); textarea.focus();
baseHeight = doc.selection.createRange().duplicate().boundingHeight; baseHeight = doc.selection.createRange().duplicate().boundingHeight;
if (!document.forms[form_name]) if (!document.forms[form_name]) {
{
document.body.focus(); document.body.focus();
} }
} }
@ -57,69 +51,59 @@ function initInsertions()
/** /**
* bbstyle * bbstyle
*/ */
function bbstyle(bbnumber) function bbstyle(bbnumber) {
{ if (bbnumber !== -1) {
if (bbnumber != -1)
{
bbfontstyle(bbtags[bbnumber], bbtags[bbnumber+1]); bbfontstyle(bbtags[bbnumber], bbtags[bbnumber+1]);
} } else {
else
{
insert_text('[*]'); insert_text('[*]');
document.forms[form_name].elements[text_name].focus(); document.forms[form_name].elements[text_name].focus();
} }
} }
/** /**
* Apply bbcodes * Apply bbcodes
*/ */
function bbfontstyle(bbopen, bbclose) function bbfontstyle(bbopen, bbclose) {
{
theSelection = false; theSelection = false;
var textarea = document.forms[form_name].elements[text_name]; var textarea = document.forms[form_name].elements[text_name];
textarea.focus(); textarea.focus();
if ((clientVer >= 4) && is_ie && is_win) if ((clientVer >= 4) && is_ie && is_win) {
{
// Get text selection // Get text selection
theSelection = document.selection.createRange().text; theSelection = document.selection.createRange().text;
if (theSelection) if (theSelection) {
{
// Add tags around selection // Add tags around selection
document.selection.createRange().text = bbopen + theSelection + bbclose; document.selection.createRange().text = bbopen + theSelection + bbclose;
document.forms[form_name].elements[text_name].focus(); document.forms[form_name].elements[text_name].focus();
theSelection = ''; theSelection = '';
return; return;
} }
} } else if (document.forms[form_name].elements[text_name].selectionEnd
else if (document.forms[form_name].elements[text_name].selectionEnd && (document.forms[form_name].elements[text_name].selectionEnd - document.forms[form_name].elements[text_name].selectionStart > 0)) && (document.forms[form_name].elements[text_name].selectionEnd - document.forms[form_name].elements[text_name].selectionStart > 0)) {
{
mozWrap(document.forms[form_name].elements[text_name], bbopen, bbclose); mozWrap(document.forms[form_name].elements[text_name], bbopen, bbclose);
document.forms[form_name].elements[text_name].focus(); document.forms[form_name].elements[text_name].focus();
theSelection = ''; theSelection = '';
return; return;
} }
//The new position for the cursor after adding the bbcode //The new position for the cursor after adding the bbcode
var caret_pos = getCaretPosition(textarea).start; var caret_pos = getCaretPosition(textarea).start;
var new_pos = caret_pos + bbopen.length; var new_pos = caret_pos + bbopen.length;
// Open tag // Open tag
insert_text(bbopen + bbclose); insert_text(bbopen + bbclose);
// Center the cursor when we don't have a selection // Center the cursor when we don't have a selection
// Gecko and proper browsers // Gecko and proper browsers
if (!isNaN(textarea.selectionStart)) if (!isNaN(textarea.selectionStart)) {
{
textarea.selectionStart = new_pos; textarea.selectionStart = new_pos;
textarea.selectionEnd = new_pos; textarea.selectionEnd = new_pos;
} }
// IE // IE
else if (document.selection) else if (document.selection) {
{
var range = textarea.createTextRange(); var range = textarea.createTextRange();
range.move("character", new_pos); range.move("character", new_pos);
range.select(); range.select();
@ -133,62 +117,47 @@ function bbfontstyle(bbopen, bbclose)
/** /**
* Insert text at position * Insert text at position
*/ */
function insert_text(text, spaces, popup) function insert_text(text, spaces, popup) {
{
var textarea; var textarea;
if (!popup) if (!popup) {
{
textarea = document.forms[form_name].elements[text_name]; textarea = document.forms[form_name].elements[text_name];
} } else {
else
{
textarea = opener.document.forms[form_name].elements[text_name]; textarea = opener.document.forms[form_name].elements[text_name];
} }
if (spaces) if (spaces) {
{
text = ' ' + text + ' '; text = ' ' + text + ' ';
} }
if (!isNaN(textarea.selectionStart)) if (!isNaN(textarea.selectionStart)) {
{
var sel_start = textarea.selectionStart; var sel_start = textarea.selectionStart;
var sel_end = textarea.selectionEnd; var sel_end = textarea.selectionEnd;
mozWrap(textarea, text, ''); mozWrap(textarea, text, '');
textarea.selectionStart = sel_start + text.length; textarea.selectionStart = sel_start + text.length;
textarea.selectionEnd = sel_end + text.length; textarea.selectionEnd = sel_end + text.length;
} } else if (textarea.createTextRange && textarea.caretPos) {
if (baseHeight !== textarea.caretPos.boundingHeight) {
else if (textarea.createTextRange && textarea.caretPos)
{
if (baseHeight != textarea.caretPos.boundingHeight)
{
textarea.focus(); textarea.focus();
storeCaret(textarea); storeCaret(textarea);
} }
var caret_pos = textarea.caretPos; var caret_pos = textarea.caretPos;
caret_pos.text = caret_pos.text.charAt(caret_pos.text.length - 1) == ' ' ? caret_pos.text + text + ' ' : caret_pos.text + text; caret_pos.text = caret_pos.text.charAt(caret_pos.text.length - 1) === ' ' ? caret_pos.text + text + ' ' : caret_pos.text + text;
} else {
}
else
{
textarea.value = textarea.value + text; textarea.value = textarea.value + text;
} }
if (!popup) if (!popup) {
{
textarea.focus(); textarea.focus();
} }
} }
/** /**
* Add inline attachment at position * Add inline attachment at position
*/ */
function attach_inline(index, filename) function attach_inline(index, filename) {
{
insert_text('[attachment=' + index + ']' + filename + '[/attachment]'); insert_text('[attachment=' + index + ']' + filename + '[/attachment]');
document.forms[form_name].elements[text_name].focus(); document.forms[form_name].elements[text_name].focus();
} }
@ -202,56 +171,39 @@ function addquote(post_id, username)
var theSelection = ''; var theSelection = '';
var divarea = false; var divarea = false;
if (document.all) if (document.all) {
{
divarea = document.all[message_name]; divarea = document.all[message_name];
} } else {
else
{
divarea = document.getElementById(message_name); divarea = document.getElementById(message_name);
} }
// Get text selection - not only the post content :( // Get text selection - not only the post content :(
if (window.getSelection) if (window.getSelection) {
{
theSelection = window.getSelection().toString(); theSelection = window.getSelection().toString();
} } else if (document.getSelection) {
else if (document.getSelection)
{
theSelection = document.getSelection(); theSelection = document.getSelection();
} } else if (document.selection) {
else if (document.selection)
{
theSelection = document.selection.createRange().text; theSelection = document.selection.createRange().text;
} }
if (theSelection == '' || typeof theSelection == 'undefined' || theSelection == null) if (theSelection === '' || typeof theSelection === 'undefined' || theSelection === null) {
{ if (divarea.innerHTML) {
if (divarea.innerHTML)
{
theSelection = divarea.innerHTML.replace(/<br>/ig, '\n'); theSelection = divarea.innerHTML.replace(/<br>/ig, '\n');
theSelection = theSelection.replace(/<br\/>/ig, '\n'); theSelection = theSelection.replace(/<br\/>/ig, '\n');
theSelection = theSelection.replace(/&lt\;/ig, '<'); theSelection = theSelection.replace(/&lt\;/ig, '<');
theSelection = theSelection.replace(/&gt\;/ig, '>'); theSelection = theSelection.replace(/&gt\;/ig, '>');
theSelection = theSelection.replace(/&amp\;/ig, '&'); theSelection = theSelection.replace(/&amp\;/ig, '&');
theSelection = theSelection.replace(/&nbsp\;/ig, ' '); theSelection = theSelection.replace(/&nbsp\;/ig, ' ');
} } else if (document.all) {
else if (document.all)
{
theSelection = divarea.innerText; theSelection = divarea.innerText;
} } else if (divarea.textContent) {
else if (divarea.textContent)
{
theSelection = divarea.textContent; theSelection = divarea.textContent;
} } else if (divarea.firstChild.nodeValue) {
else if (divarea.firstChild.nodeValue)
{
theSelection = divarea.firstChild.nodeValue; theSelection = divarea.firstChild.nodeValue;
} }
} }
if (theSelection) if (theSelection) {
{
insert_text('[quote="' + username + '"]' + theSelection + '[/quote]'); insert_text('[quote="' + username + '"]' + theSelection + '[/quote]');
} }
@ -261,15 +213,13 @@ function addquote(post_id, username)
/** /**
* From http://www.massless.org/mozedit/ * From http://www.massless.org/mozedit/
*/ */
function mozWrap(txtarea, open, close) function mozWrap(txtarea, open, close) {
{ var selLength = (typeof(txtarea.textLength) === 'undefined') ? txtarea.value.length : txtarea.textLength;
var selLength = (typeof(txtarea.textLength) == 'undefined') ? txtarea.value.length : txtarea.textLength;
var selStart = txtarea.selectionStart; var selStart = txtarea.selectionStart;
var selEnd = txtarea.selectionEnd; var selEnd = txtarea.selectionEnd;
var scrollTop = txtarea.scrollTop; var scrollTop = txtarea.scrollTop;
if (selEnd == 1 || selEnd == 2) if (selEnd === 1 || selEnd === 2) {
{
selEnd = selLength; selEnd = selLength;
} }
@ -290,10 +240,8 @@ function mozWrap(txtarea, open, close)
* Insert at Caret position. Code from * Insert at Caret position. Code from
* http://www.faqts.com/knowledge_base/view.phtml/aid/1052/fid/130 * http://www.faqts.com/knowledge_base/view.phtml/aid/1052/fid/130
*/ */
function storeCaret(textEl) function storeCaret(textEl) {
{ if (textEl.createTextRange) {
if (textEl.createTextRange)
{
textEl.caretPos = document.selection.createRange().duplicate(); textEl.caretPos = document.selection.createRange().duplicate();
} }
} }
@ -301,8 +249,7 @@ function storeCaret(textEl)
/** /**
* Color pallette * Color pallette
*/ */
function colorPalette(dir, width, height) function colorPalette(dir, width, height) {
{
var r = 0, g = 0, b = 0; var r = 0, g = 0, b = 0;
var numberList = new Array(6); var numberList = new Array(6);
var color = ''; var color = '';
@ -315,88 +262,74 @@ function colorPalette(dir, width, height)
document.writeln('<table class="type2">'); document.writeln('<table class="type2">');
for (r = 0; r < 5; r++) for (r = 0; r < 5; r++) {
{ if (dir === 'h') {
if (dir == 'h')
{
document.writeln('<tr>'); document.writeln('<tr>');
} }
for (g = 0; g < 5; g++) for (g = 0; g < 5; g++) {
{ if (dir === 'v') {
if (dir == 'v')
{
document.writeln('<tr>'); document.writeln('<tr>');
} }
for (b = 0; b < 5; b++) for (b = 0; b < 5; b++) {
{
color = String(numberList[r]) + String(numberList[g]) + String(numberList[b]); color = String(numberList[r]) + String(numberList[g]) + String(numberList[b]);
document.write('<td bgcolor="#' + color + '" style="width: ' + width + 'px; height: ' + height + 'px;">'); document.write('<td bgcolor="#' + color + '" style="width: ' + width + 'px; height: ' + height + 'px;">');
document.write('<a href="#" onclick="bbfontstyle(\'[color=#' + color + ']\', \'[/color]\'); return false;"><img src="images/spacer.gif" width="' + width + '" height="' + height + '" alt="#' + color + '" title="#' + color + '" /></a>'); document.write('<a href="#" onclick="bbfontstyle(\'[color=#' + color + ']\', \'[/color]\'); return false;"><img src="images/spacer.gif" width="' + width + '" height="' + height + '" alt="#' + color + '" title="#' + color + '" /></a>');
document.writeln('</td>'); document.writeln('</td>');
} }
if (dir == 'v') if (dir === 'v') {
{
document.writeln('</tr>'); document.writeln('</tr>');
} }
} }
if (dir == 'h') if (dir === 'h') {
{
document.writeln('</tr>'); document.writeln('</tr>');
} }
} }
document.writeln('</table>'); document.writeln('</table>');
} }
/** /**
* Caret Position object * Caret Position object
*/ */
function caretPosition() function caretPosition() {
{
var start = null; var start = null;
var end = null; var end = null;
} }
/** /**
* Get the caret position in an textarea * Get the caret position in an textarea
*/ */
function getCaretPosition(txtarea) function getCaretPosition(txtarea) {
{
var caretPos = new caretPosition(); var caretPos = new caretPosition();
// simple Gecko/Opera way // simple Gecko/Opera way
if (txtarea.selectionStart || txtarea.selectionStart == 0) if (txtarea.selectionStart || txtarea.selectionStart === 0) {
{
caretPos.start = txtarea.selectionStart; caretPos.start = txtarea.selectionStart;
caretPos.end = txtarea.selectionEnd; caretPos.end = txtarea.selectionEnd;
} }
// dirty and slow IE way // dirty and slow IE way
else if (document.selection) else if (document.selection) {
{
// get current selection // get current selection
var range = document.selection.createRange(); var range = document.selection.createRange();
// a new selection of the whole textarea // a new selection of the whole textarea
var range_all = document.body.createTextRange(); var range_all = document.body.createTextRange();
range_all.moveToElementText(txtarea); range_all.moveToElementText(txtarea);
// calculate selection start point by moving beginning of range_all to beginning of range // calculate selection start point by moving beginning of range_all to beginning of range
var sel_start; var sel_start;
for (sel_start = 0; range_all.compareEndPoints('StartToStart', range) < 0; sel_start++) for (sel_start = 0; range_all.compareEndPoints('StartToStart', range) < 0; sel_start++) {
{
range_all.moveStart('character', 1); range_all.moveStart('character', 1);
} }
txtarea.sel_start = sel_start; txtarea.sel_start = sel_start;
// we ignore the end value for IE, this is already dirty enough and we don't need it // we ignore the end value for IE, this is already dirty enough and we don't need it
caretPos.start = txtarea.sel_start; caretPos.start = txtarea.sel_start;
caretPos.end = txtarea.sel_start; caretPos.end = txtarea.sel_start;
} }
return caretPos; return caretPos;

View file

@ -2,35 +2,27 @@
* Hide and show all checkboxes * Hide and show all checkboxes
* status = true (show boxes), false (hide boxes) * status = true (show boxes), false (hide boxes)
*/ */
function display_checkboxes(status) function display_checkboxes(status) {
{
var form = document.getElementById('set-permissions'); var form = document.getElementById('set-permissions');
var cb = document.getElementsByTagName('input'); var cb = document.getElementsByTagName('input');
var display; var display;
//show //show
if (status) if (status) {
{
display = 'inline'; display = 'inline';
} }
//hide //hide
else else {
{
display = 'none'; display = 'none';
} }
for (var i = 0; i < cb.length; i++ ) for (var i = 0; i < cb.length; i++ ) {
{ if (cb[i].className === 'permissions-checkbox') {
if (cb[i].className == 'permissions-checkbox')
{
cb[i].style.display = display; cb[i].style.display = display;
} }
}
}
} }
/** /**
* Change opacity of element * Change opacity of element
* e = element * e = element
@ -38,7 +30,7 @@ function display_checkboxes(status)
*/ */
function set_opacity(e, value) { function set_opacity(e, value) {
e.style.opacity = value/10; e.style.opacity = value/10;
//IE opacity currently turned off, because of its astronomical stupidity //IE opacity currently turned off, because of its astronomical stupidity
//e.style.filter = 'alpha(opacity=' + value*10 + ')'; //e.style.filter = 'alpha(opacity=' + value*10 + ')';
} }
@ -50,13 +42,10 @@ function set_opacity(e, value) {
function toggle_opacity(block_id) { function toggle_opacity(block_id) {
var cb = document.getElementById('checkbox' + block_id); var cb = document.getElementById('checkbox' + block_id);
var fs = document.getElementById('perm' + block_id); var fs = document.getElementById('perm' + block_id);
if (cb.checked) if (cb.checked) {
{
set_opacity(fs, 5); set_opacity(fs, 5);
} } else {
else
{
set_opacity(fs, 10); set_opacity(fs, 10);
} }
} }
@ -71,21 +60,17 @@ function reset_opacity(status, except_id) {
var fs = perm.getElementsByTagName('fieldset'); var fs = perm.getElementsByTagName('fieldset');
var opacity = 5; var opacity = 5;
if (status) if (status) {
{ opacity = 10;
opacity = 10;
} }
for (var i = 0; i < fs.length; i++ ) for (var i = 0; i < fs.length; i++ ) {
{ if (fs[i].className !== 'quick') {
if (fs[i].className != 'quick')
{
set_opacity(fs[i], opacity); set_opacity(fs[i], opacity);
} }
} }
if (typeof(except_id) != 'undefined') if (typeof(except_id) !== 'undefined') {
{
set_opacity(document.getElementById('perm' + except_id), 10); set_opacity(document.getElementById('perm' + except_id), 10);
} }
@ -93,20 +78,15 @@ function reset_opacity(status, except_id) {
marklist('set-permissions', 'inherit', !status); marklist('set-permissions', 'inherit', !status);
} }
/** /**
* Check whether we have a full radiobutton row of true * Check whether we have a full radiobutton row of true
* index = offset for the row of inputs (0 == first row, 1 == second, 2 == third), * index = offset for the row of inputs (0 == first row, 1 == second, 2 == third),
* rb = array of radiobuttons * rb = array of radiobuttons
*/ */
function get_radio_status(index, rb) function get_radio_status(index, rb) {
{ for (var i = index; i < rb.length; i = i + 3 ) {
for (var i = index; i < rb.length; i = i + 3 ) if (rb[i].checked !== true) {
{ if (i > index) {
if (rb[i].checked != true)
{
if (i > index)
{
//at least one is true, but not all (custom) //at least one is true, but not all (custom)
return 2; return 2;
} }
@ -121,17 +101,15 @@ function get_radio_status(index, rb)
/** /**
* Set tab colours * Set tab colours
* id = panel the tab needs to be set for, * id = panel the tab needs to be set for,
* init = initialising on open, * init = initialising on open,
* quick = If no calculation needed, this contains the colour * quick = If no calculation needed, this contains the colour
*/ */
function set_colours(id, init, quick) function set_colours(id, init, quick) {
{
var table = document.getElementById('table' + id); var table = document.getElementById('table' + id);
var tab = document.getElementById('tab' + id); var tab = document.getElementById('tab' + id);
if (typeof(quick) != 'undefined') if (typeof(quick) !== 'undefined') {
{
tab.className = 'permissions-preset-' + quick + ' activetab'; tab.className = 'permissions-preset-' + quick + ' activetab';
return; return;
} }
@ -141,37 +119,27 @@ function set_colours(id, init, quick)
var status = get_radio_status(0, rb); var status = get_radio_status(0, rb);
if (status == 1) if (status === 1) {
{
colour = 'yes'; colour = 'yes';
} } else if (status === 0) {
else if (status == 0)
{
// We move on to No // We move on to No
status = get_radio_status(1, rb); status = get_radio_status(1, rb);
if (status == 1) if (status === 1) {
{
colour = 'no'; colour = 'no';
} } else if (status === 0) {
else if (status == 0)
{
// We move on to Never // We move on to Never
status = get_radio_status(2, rb); status = get_radio_status(2, rb);
if (status == 1) if (status === 1) {
{
colour = 'never'; colour = 'never';
} }
} }
} }
if (init) if (init) {
{
tab.className = 'permissions-preset-' + colour; tab.className = 'permissions-preset-' + colour;
} } else {
else
{
tab.className = 'permissions-preset-' + colour + ' activetab'; tab.className = 'permissions-preset-' + colour + ' activetab';
} }
} }
@ -180,16 +148,13 @@ function set_colours(id, init, quick)
* Initialise advanced tab colours on first load * Initialise advanced tab colours on first load
* block_id = block that is opened * block_id = block that is opened
*/ */
function init_colours(block_id) function init_colours(block_id) {
{
var block = document.getElementById('advanced' + block_id); var block = document.getElementById('advanced' + block_id);
var panels = block.getElementsByTagName('div'); var panels = block.getElementsByTagName('div');
var tab = document.getElementById('tab' + id); var tab = document.getElementById('tab' + id);
for (var i = 0; i < panels.length; i++) for (var i = 0; i < panels.length; i++) {
{ if (panels[i].className === 'permissions-panel') {
if(panels[i].className == 'permissions-panel')
{
set_colours(panels[i].id.replace(/options/, ''), true); set_colours(panels[i].id.replace(/options/, ''), true);
} }
} }
@ -203,17 +168,15 @@ function init_colours(block_id)
* adv = we are opening advanced permissions * adv = we are opening advanced permissions
* view = called from view permissions * view = called from view permissions
*/ */
function swap_options(pmask, fmask, cat, adv, view) function swap_options(pmask, fmask, cat, adv, view) {
{
id = pmask + fmask + cat; id = pmask + fmask + cat;
active_option = active_pmask + active_fmask + active_cat; active_option = active_pmask + active_fmask + active_cat;
var old_tab = document.getElementById('tab' + active_option); var old_tab = document.getElementById('tab' + active_option);
var new_tab = document.getElementById('tab' + id); var new_tab = document.getElementById('tab' + id);
var adv_block = document.getElementById('advanced' + pmask + fmask); var adv_block = document.getElementById('advanced' + pmask + fmask);
if (adv_block.style.display == 'block' && adv == true) if (adv_block.style.display === 'block' && adv === true) {
{
dE('advanced' + pmask + fmask, -1); dE('advanced' + pmask + fmask, -1);
reset_opacity(1); reset_opacity(1);
display_checkboxes(false); display_checkboxes(false);
@ -221,20 +184,16 @@ function swap_options(pmask, fmask, cat, adv, view)
} }
// no need to set anything if we are clicking on the same tab again // no need to set anything if we are clicking on the same tab again
if (new_tab == old_tab && !adv) if (new_tab === old_tab && !adv) {
{
return; return;
} }
// init colours // init colours
if (adv && (pmask + fmask) != (active_pmask + active_fmask)) if (adv && (pmask + fmask) !== (active_pmask + active_fmask)) {
{
init_colours(pmask + fmask); init_colours(pmask + fmask);
display_checkboxes(true); display_checkboxes(true);
reset_opacity(1); reset_opacity(1);
} } else if (adv) {
else if (adv)
{
//Checkbox might have been clicked, but we need full visibility //Checkbox might have been clicked, but we need full visibility
display_checkboxes(true); display_checkboxes(true);
reset_opacity(1); reset_opacity(1);
@ -244,31 +203,26 @@ function swap_options(pmask, fmask, cat, adv, view)
old_tab.className = old_tab.className.replace(/\ activetab/g, ''); old_tab.className = old_tab.className.replace(/\ activetab/g, '');
new_tab.className = new_tab.className + ' activetab'; new_tab.className = new_tab.className + ' activetab';
if (id == active_option && adv != true) if (id === active_option && adv !== true) {
{
return; return;
} }
dE('options' + active_option, -1); dE('options' + active_option, -1);
//hiding and showing the checkbox //hiding and showing the checkbox
if (document.getElementById('checkbox' + active_pmask + active_fmask)) if (document.getElementById('checkbox' + active_pmask + active_fmask)) {
{ dE('checkbox' + pmask + fmask, -1);
dE('checkbox' + pmask + fmask, -1);
if ((pmask + fmask) !== (active_pmask + active_fmask)) {
if ((pmask + fmask) != (active_pmask + active_fmask))
{
document.getElementById('checkbox' + active_pmask + active_fmask).style.display = 'inline'; document.getElementById('checkbox' + active_pmask + active_fmask).style.display = 'inline';
} }
} }
if (!view) if (!view) {
{
dE('advanced' + active_pmask + active_fmask, -1); dE('advanced' + active_pmask + active_fmask, -1);
} }
if (!view) if (!view) {
{
dE('advanced' + pmask + fmask, 1); dE('advanced' + pmask + fmask, 1);
} }
dE('options' + id, 1); dE('options' + id, 1);
@ -282,41 +236,33 @@ function swap_options(pmask, fmask, cat, adv, view)
* Mark all radio buttons in one panel * Mark all radio buttons in one panel
* id = table ID container, s = status ['y'/'u'/'n'] * id = table ID container, s = status ['y'/'u'/'n']
*/ */
function mark_options(id, s) function mark_options(id, s) {
{
var t = document.getElementById(id); var t = document.getElementById(id);
if (!t) if (!t) {
{
return; return;
} }
var rb = t.getElementsByTagName('input'); var rb = t.getElementsByTagName('input');
for (var r = 0; r < rb.length; r++) for (var r = 0; r < rb.length; r++) {
{ if (rb[r].id.substr(rb[r].id.length-1) === s) {
if (rb[r].id.substr(rb[r].id.length-1) == s)
{
rb[r].checked = true; rb[r].checked = true;
} }
} }
} }
function mark_one_option(id, field_name, s) function mark_one_option(id, field_name, s) {
{
var t = document.getElementById(id); var t = document.getElementById(id);
if (!t) if (!t) {
{
return; return;
} }
var rb = t.getElementsByTagName('input'); var rb = t.getElementsByTagName('input');
for (var r = 0; r < rb.length; r++) for (var r = 0; r < rb.length; r++) {
{ if (rb[r].id.substr(rb[r].id.length-field_name.length-3, field_name.length) === field_name && rb[r].id.substr(rb[r].id.length-1) === s) {
if (rb[r].id.substr(rb[r].id.length-field_name.length-3, field_name.length) == field_name && rb[r].id.substr(rb[r].id.length-1) == s)
{
rb[r].checked = true; rb[r].checked = true;
} }
} }
@ -325,12 +271,10 @@ function mark_one_option(id, field_name, s)
/** /**
* Reset role dropdown field to Select role... if an option gets changed * Reset role dropdown field to Select role... if an option gets changed
*/ */
function reset_role(id) function reset_role(id) {
{
var t = document.getElementById(id); var t = document.getElementById(id);
if (!t) if (!t) {
{
return; return;
} }
@ -340,20 +284,17 @@ function reset_role(id)
/** /**
* Load role and set options accordingly * Load role and set options accordingly
*/ */
function set_role_settings(role_id, target_id) function set_role_settings(role_id, target_id) {
{
settings = role_options[role_id]; settings = role_options[role_id];
if (!settings) if (!settings) {
{
return; return;
} }
// Mark all options to no (unset) first... // Mark all options to no (unset) first...
mark_options(target_id, 'u'); mark_options(target_id, 'u');
for (var r in settings) for (var r in settings) {
{ mark_one_option(target_id, r, (settings[r] === 1) ? 'y' : 'n');
mark_one_option(target_id, r, (settings[r] == 1) ? 'y' : 'n');
} }
} }

View file

@ -1,5 +1,7 @@
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
"use strict";
$('#tz_date').change(function() { $('#tz_date').change(function() {
phpbb.timezoneSwitchDate(false); phpbb.timezoneSwitchDate(false);
}); });

View file

@ -1,6 +1,6 @@
/* /*
javascript for Bubble Tooltips by Alessandro Fulciniti javascript for Bubble Tooltips by Alessandro Fulciniti
- http://pro.html.it - http://web-graphics.com - http://pro.html.it - http://web-graphics.com
obtained from: http://web-graphics.com/mtarchive/001717.php obtained from: http://web-graphics.com/mtarchive/001717.php
phpBB Development Team: phpBB Development Team:
@ -15,14 +15,12 @@ var head_text, tooltip_mode;
/** /**
* Enable tooltip replacements for links * Enable tooltip replacements for links
*/ */
function enable_tooltips_link(id, headline, sub_id) function enable_tooltips_link(id, headline, sub_id) {
{
var links, i, hold; var links, i, hold;
head_text = headline; head_text = headline;
if (!document.getElementById || !document.getElementsByTagName) if (!document.getElementById || !document.getElementsByTagName) {
{
return; return;
} }
@ -33,26 +31,18 @@ function enable_tooltips_link(id, headline, sub_id)
document.getElementsByTagName('body')[0].appendChild(hold); document.getElementsByTagName('body')[0].appendChild(hold);
if (id == null) if (id === null) {
{
links = document.getElementsByTagName('a'); links = document.getElementsByTagName('a');
} } else {
else
{
links = document.getElementById(id).getElementsByTagName('a'); links = document.getElementById(id).getElementsByTagName('a');
} }
for (i = 0; i < links.length; i++) for (i = 0; i < links.length; i++) {
{ if (sub_id) {
if (sub_id) if (links[i].id.substr(0, sub_id.length) === sub_id) {
{
if (links[i].id.substr(0, sub_id.length) == sub_id)
{
prepare(links[i]); prepare(links[i]);
} }
} } else {
else
{
prepare(links[i]); prepare(links[i]);
} }
} }
@ -63,14 +53,12 @@ function enable_tooltips_link(id, headline, sub_id)
/** /**
* Enable tooltip replacements for selects * Enable tooltip replacements for selects
*/ */
function enable_tooltips_select(id, headline, sub_id) function enable_tooltips_select(id, headline, sub_id) {
{
var links, i, hold; var links, i, hold;
head_text = headline; head_text = headline;
if (!document.getElementById || !document.getElementsByTagName) if (!document.getElementById || !document.getElementsByTagName) {
{
return; return;
} }
@ -81,26 +69,18 @@ function enable_tooltips_select(id, headline, sub_id)
document.getElementsByTagName('body')[0].appendChild(hold); document.getElementsByTagName('body')[0].appendChild(hold);
if (id == null) if (id === null) {
{
links = document.getElementsByTagName('option'); links = document.getElementsByTagName('option');
} } else {
else
{
links = document.getElementById(id).getElementsByTagName('option'); links = document.getElementById(id).getElementsByTagName('option');
} }
for (i = 0; i < links.length; i++) for (i = 0; i < links.length; i++) {
{ if (sub_id) {
if (sub_id) if (links[i].parentNode.id.substr(0, sub_id.length) === sub_id) {
{
if (links[i].parentNode.id.substr(0, sub_id.length) == sub_id)
{
prepare(links[i]); prepare(links[i]);
} }
} } else {
else
{
prepare(links[i]); prepare(links[i]);
} }
} }
@ -111,14 +91,12 @@ function enable_tooltips_select(id, headline, sub_id)
/** /**
* Prepare elements to replace * Prepare elements to replace
*/ */
function prepare(element) function prepare(element) {
{
var tooltip, text, desc, title; var tooltip, text, desc, title;
text = element.getAttribute('title'); text = element.getAttribute('title');
if (text == null || text.length == 0) if (text === null || text.length === 0) {
{
return; return;
} }
@ -139,8 +117,7 @@ function prepare(element)
element.onmouseover = show_tooltip; element.onmouseover = show_tooltip;
element.onmouseout = hide_tooltip; element.onmouseout = hide_tooltip;
if (tooltip_mode == 'link') if (tooltip_mode === 'link') {
{
element.onmousemove = locate; element.onmousemove = locate;
} }
} }
@ -148,8 +125,7 @@ function prepare(element)
/** /**
* Show tooltip * Show tooltip
*/ */
function show_tooltip(e) function show_tooltip(e) {
{
document.getElementById('_tooltip_container').appendChild(this.tooltip); document.getElementById('_tooltip_container').appendChild(this.tooltip);
locate(this); locate(this);
} }
@ -157,11 +133,9 @@ function show_tooltip(e)
/** /**
* Hide tooltip * Hide tooltip
*/ */
function hide_tooltip(e) function hide_tooltip(e) {
{
var d = document.getElementById('_tooltip_container'); var d = document.getElementById('_tooltip_container');
if (d.childNodes.length > 0) if (d.childNodes.length > 0) {
{
d.removeChild(d.firstChild); d.removeChild(d.firstChild);
} }
} }
@ -169,8 +143,7 @@ function hide_tooltip(e)
/** /**
* Set opacity on tooltip element * Set opacity on tooltip element
*/ */
function set_opacity(element) function set_opacity(element) {
{
element.style.filter = 'alpha(opacity:95)'; element.style.filter = 'alpha(opacity:95)';
element.style.KHTMLOpacity = '0.95'; element.style.KHTMLOpacity = '0.95';
element.style.MozOpacity = '0.95'; element.style.MozOpacity = '0.95';
@ -180,8 +153,7 @@ function set_opacity(element)
/** /**
* Create new element * Create new element
*/ */
function create_element(tag, c) function create_element(tag, c) {
{
var x = document.createElement(tag); var x = document.createElement(tag);
x.className = c; x.className = c;
x.style.display = 'block'; x.style.display = 'block';
@ -191,34 +163,26 @@ function create_element(tag, c)
/** /**
* Correct positioning of tooltip container * Correct positioning of tooltip container
*/ */
function locate(e) function locate(e) {
{
var posx = 0; var posx = 0;
var posy = 0; var posy = 0;
e = e.parentNode; e = e.parentNode;
if (e.offsetParent) if (e.offsetParent) {
{ for (posx = 0, posy = 0; e.offsetParent; e = e.offsetParent) {
for (var posx = 0, posy = 0; e.offsetParent; e = e.offsetParent)
{
posx += e.offsetLeft; posx += e.offsetLeft;
posy += e.offsetTop; posy += e.offsetTop;
} }
} } else {
else
{
posx = e.offsetLeft; posx = e.offsetLeft;
posy = e.offsetTop; posy = e.offsetTop;
} }
if (tooltip_mode == 'link') if (tooltip_mode === 'link') {
{
document.getElementById('_tooltip_container').style.top=(posy+20) + 'px'; document.getElementById('_tooltip_container').style.top=(posy+20) + 'px';
document.getElementById('_tooltip_container').style.left=(posx-20) + 'px'; document.getElementById('_tooltip_container').style.left=(posx-20) + 'px';
} } else {
else
{
document.getElementById('_tooltip_container').style.top=(posy+30) + 'px'; document.getElementById('_tooltip_container').style.top=(posy+30) + 'px';
document.getElementById('_tooltip_container').style.left=(posx-205) + 'px'; document.getElementById('_tooltip_container').style.left=(posx-205) + 'px';
} }

View file

@ -57,7 +57,7 @@ phpbb.clearLoadingTimeout = function() {
* @param string title Title of the message, eg "Information" (HTML). * @param string title Title of the message, eg "Information" (HTML).
* @param string msg Message to display (HTML). * @param string msg Message to display (HTML).
* @param bool fadedark Remove the dark background when done? Defaults * @param bool fadedark Remove the dark background when done? Defaults
* to yes. * to yes.
* *
* @returns object Returns the div created. * @returns object Returns the div created.
*/ */
@ -121,9 +121,9 @@ phpbb.alert = function(title, msg, fadedark) {
* *
* @param string msg Message to display (HTML). * @param string msg Message to display (HTML).
* @param function callback Callback. Bool param, whether the user pressed * @param function callback Callback. Bool param, whether the user pressed
* yes or no (or whatever their language is). * yes or no (or whatever their language is).
* @param bool fadedark Remove the dark background when done? Defaults * @param bool fadedark Remove the dark background when done? Defaults
* to yes. * to yes.
* *
* @returns object Returns the div created. * @returns object Returns the div created.
*/ */
@ -136,7 +136,7 @@ phpbb.confirm = function(msg, callback, fadedark) {
}); });
var clickHandler = function(e) { var clickHandler = function(e) {
var res = this.className === 'button1'; var res = this.name === 'confirm';
var fade = (typeof fadedark !== 'undefined' && !fadedark && res) ? div : dark; var fade = (typeof fadedark !== 'undefined' && !fadedark && res) ? div : dark;
fade.fadeOut(phpbb.alertTime, function() { fade.fadeOut(phpbb.alertTime, function() {
div.hide(); div.hide();
@ -164,11 +164,11 @@ phpbb.confirm = function(msg, callback, fadedark) {
$(document).bind('keydown', function(e) { $(document).bind('keydown', function(e) {
if (e.keyCode === keymap.ENTER) { if (e.keyCode === keymap.ENTER) {
$('input[type="button"].button1').trigger('click'); $('input[name="confirm"]').trigger('click');
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} else if (e.keyCode === keymap.ESC) { } else if (e.keyCode === keymap.ESC) {
$('input[type="button"].button2').trigger('click'); $('input[name="cancel"]').trigger('click');
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
@ -232,10 +232,10 @@ phpbb.parseQuerystring = function(string) {
* *
* @param object options Options. * @param object options Options.
* @param bool/function refresh If we are sent back a refresh, should it be * @param bool/function refresh If we are sent back a refresh, should it be
* acted upon? This can either be true / false / a function. * acted upon? This can either be true / false / a function.
* @param function callback Callback to call on completion of event. Has * @param function callback Callback to call on completion of event. Has
* three parameters: the element that the event was evoked from, the JSON * three parameters: the element that the event was evoked from, the JSON
* that was returned and (if it is a form) the form action. * that was returned and (if it is a form) the form action.
*/ */
phpbb.ajaxify = function(options) { phpbb.ajaxify = function(options) {
var elements = $(options.selector), var elements = $(options.selector),
@ -252,6 +252,11 @@ phpbb.ajaxify = function(options) {
return; return;
} }
function errorHandler() {
phpbb.clearLoadingTimeout();
phpbb.alert(dark.attr('data-ajax-error-title'), dark.attr('data-ajax-error-text'));
}
/** /**
* This is a private function used to handle the callbacks, refreshes * This is a private function used to handle the callbacks, refreshes
* and alert. It calls the callback, refreshes the page if necessary, and * and alert. It calls the callback, refreshes the page if necessary, and
@ -320,13 +325,6 @@ phpbb.ajaxify = function(options) {
} }
} }
function errorHandler() {
var alert;
phpbb.clearLoadingTimeout();
alert = phpbb.alert(dark.attr('data-ajax-error-title'), dark.attr('data-ajax-error-text'));
}
// If the element is a form, POST must be used and some extra data must // If the element is a form, POST must be used and some extra data must
// be taken from the form. // be taken from the form.
var runFilter = (typeof options.filter === 'function'); var runFilter = (typeof options.filter === 'function');
@ -355,8 +353,7 @@ phpbb.ajaxify = function(options) {
return; return;
} }
if (overlay && (typeof $this.attr('data-overlay') === 'undefined' || $this.attr('data-overlay') == 'true')) if (overlay && (typeof $this.attr('data-overlay') === 'undefined' || $this.attr('data-overlay') === 'true')) {
{
phpbb.loadingAlert(); phpbb.loadingAlert();
} }
@ -389,7 +386,7 @@ phpbb.ajaxify = function(options) {
* @param bool keepSelection Shall we keep the value selected, or shall the user be forced to repick one. * @param bool keepSelection Shall we keep the value selected, or shall the user be forced to repick one.
*/ */
phpbb.timezoneSwitchDate = function(keepSelection) { phpbb.timezoneSwitchDate = function(keepSelection) {
if ($('#timezone_copy').length == 0) { if ($('#timezone_copy').length === 0) {
// We make a backup of the original dropdown, so we can remove optgroups // We make a backup of the original dropdown, so we can remove optgroups
// instead of setting display to none, because IE and chrome will not // instead of setting display to none, because IE and chrome will not
// hide options inside of optgroups and selects via css // hide options inside of optgroups and selects via css
@ -399,17 +396,17 @@ phpbb.timezoneSwitchDate = function(keepSelection) {
$('#timezone').replaceWith($('#timezone_copy').clone().attr('id', 'timezone').css('display', 'block').attr('name', 'tz')); $('#timezone').replaceWith($('#timezone_copy').clone().attr('id', 'timezone').css('display', 'block').attr('name', 'tz'));
} }
if ($('#tz_date').val() != '') { if ($('#tz_date').val() !== '') {
$('#timezone > optgroup').remove(":not([label='" + $('#tz_date').val() + "'])"); $('#timezone > optgroup').remove(":not([label='" + $('#tz_date').val() + "'])");
} }
if ($('#tz_date').val() == $('#tz_select_date_suggest').attr('data-suggested-tz')) { if ($('#tz_date').val() === $('#tz_select_date_suggest').attr('data-suggested-tz')) {
$('#tz_select_date_suggest').css('display', 'none'); $('#tz_select_date_suggest').css('display', 'none');
} else { } else {
$('#tz_select_date_suggest').css('display', 'inline'); $('#tz_select_date_suggest').css('display', 'inline');
} }
if ($("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option").size() == 1) { if ($("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option").size() === 1) {
// If there is only one timezone for the selected date, we just select that automatically. // If there is only one timezone for the selected date, we just select that automatically.
$("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option:first").attr('selected', true); $("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option:first").attr('selected', true);
keepSelection = true; keepSelection = true;
@ -440,12 +437,11 @@ phpbb.timezonePreselectSelect = function(forceSelector) {
// The offset returned here is in minutes and negated. // The offset returned here is in minutes and negated.
// http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp // http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp
var offset = (new Date()).getTimezoneOffset(); var offset = (new Date()).getTimezoneOffset();
var sign = '-';
if (offset < 0) { if (offset < 0) {
var sign = '+'; sign = '+';
offset = -offset; offset = -offset;
} else {
var sign = '-';
} }
var minutes = offset % 60; var minutes = offset % 60;
@ -466,12 +462,13 @@ phpbb.timezonePreselectSelect = function(forceSelector) {
var prefix = 'GMT' + sign + hours + ':' + minutes; var prefix = 'GMT' + sign + hours + ':' + minutes;
var prefixLength = prefix.length; var prefixLength = prefix.length;
var selectorOptions = $('#tz_date > option'); var selectorOptions = $('#tz_date > option');
var i;
for (var i = 0; i < selectorOptions.length; ++i) { for (i = 0; i < selectorOptions.length; ++i) {
var option = selectorOptions[i]; var option = selectorOptions[i];
if (option.value.substring(0, prefixLength) == prefix) { if (option.value.substring(0, prefixLength) === prefix) {
if ($('#tz_date').val() != option.value && !forceSelector) { if ($('#tz_date').val() !== option.value && !forceSelector) {
// We do not select the option for the user, but notify him, // We do not select the option for the user, but notify him,
// that we would suggest a different setting. // that we would suggest a different setting.
phpbb.timezoneSwitchDate(true); phpbb.timezoneSwitchDate(true);
@ -571,4 +568,100 @@ phpbb.addAjaxCallback('toggle_link', function() {
el.parent().attr('class', toggleClass); el.parent().attr('class', toggleClass);
}); });
/**
* Automatically resize textarea
*
* This function automatically resizes textarea elements when user
* types text.
*
* @param {jQuery} items jQuery object(s) to resize
* @param {object} options Optional parameter that adjusts default
* configuration. See configuration variable
*
* Optional parameters:
* minWindowHeight {number} Minimum browser window height when textareas are resized. Default = 500
* minHeight {number} Minimum height of textarea. Default = 200
* maxHeight {number} Maximum height of textarea. Default = 500
* heightDiff {number} Minimum difference between window and textarea height. Default = 200
* resizeCallback {function} Function to call after resizing textarea
* resetCallback {function} Function to call when resize has been canceled
* Callback function format: function(item) {}
* this points to DOM object
* item is a jQuery object, same as this
*/
phpbb.resizeTextArea = function(items, options) {
// Configuration
var configuration = {
minWindowHeight: 500,
minHeight: 200,
maxHeight: 500,
heightDiff: 200,
resizeCallback: function(item) { },
resetCallback: function(item) { }
};
if (arguments.length > 1)
{
configuration = $.extend(configuration, options);
}
function resetAutoResize(item)
{
var $item = $(item);
if ($item.hasClass('auto-resized'))
{
$(item).css({height: '', resize: ''}).removeClass('auto-resized');
configuration.resetCallback.call(item, $item);
}
}
function autoResize(item)
{
function setHeight(height)
{
$item.css({height: height + 'px', resize: 'none'}).addClass('auto-resized');
configuration.resizeCallback.call(item, $item);
}
var windowHeight = $(window).height();
if (windowHeight < configuration.minWindowHeight)
{
resetAutoResize(item);
return;
}
var maxHeight = Math.min(Math.max(windowHeight - configuration.heightDiff, configuration.minHeight), configuration.maxHeight),
$item = $(item),
height = parseInt($item.height()),
scrollHeight = (item.scrollHeight) ? item.scrollHeight : 0;
if (height > maxHeight)
{
setHeight(maxHeight);
}
else if (scrollHeight > (height + 5))
{
setHeight(Math.min(maxHeight, scrollHeight));
}
}
items.bind('focus change keyup', function() {
$(this).each(function() {
autoResize(this);
});
}).change();
$(window).resize(function() {
items.each(function() {
if ($(this).hasClass('auto-resized'))
{
autoResize(this);
}
});
});
};
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

File diff suppressed because one or more lines are too long

View file

@ -44,8 +44,11 @@ if (!defined('PHPBB_INSTALLED'))
// Replace any number of consecutive backslashes and/or slashes with a single slash // Replace any number of consecutive backslashes and/or slashes with a single slash
// (could happen on some proxy setups and/or Windows servers) // (could happen on some proxy setups and/or Windows servers)
$script_path = preg_replace('#[\\\\/]{2,}#', '/', $script_path); $script_path = preg_replace('#[\\\\/]{2,}#', '/', $script_path);
// Eliminate . and .. from the path // Eliminate . and .. from the path
$script_path = phpbb_clean_path($script_path); require($phpbb_root_path . 'includes/filesystem.' . $phpEx);
$phpbb_filesystem = new phpbb_filesystem();
$script_path = $phpbb_filesystem->clean_path($script_path);
$url = (($secure) ? 'https://' : 'http://') . $server_name; $url = (($secure) ? 'https://' : 'http://') . $server_name;
@ -82,9 +85,9 @@ require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
// Setup class loader first // Setup class loader first
$phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); $phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", $phpEx);
$phpbb_class_loader->register(); $phpbb_class_loader->register();
$phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", ".$phpEx"); $phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", $phpEx);
$phpbb_class_loader_ext->register(); $phpbb_class_loader_ext->register();
// Set up container // Set up container

View file

@ -9,6 +9,8 @@
"symfony/yaml": "2.1.*" "symfony/yaml": "2.1.*"
}, },
"require-dev": { "require-dev": {
"fabpot/goutte": "v0.1.0" "fabpot/goutte": "v0.1.0",
"phpunit/dbunit": "1.2.*",
"phpunit/phpunit": "3.7.*"
} }
} }

755
phpBB/composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ services:
arguments: arguments:
- @config - @config
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
- @cache.driver - @cache.driver
calls: calls:
- [set_name, [avatar.driver.gravatar]] - [set_name, [avatar.driver.gravatar]]
@ -16,7 +16,7 @@ services:
arguments: arguments:
- @config - @config
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
- @cache.driver - @cache.driver
calls: calls:
- [set_name, [avatar.driver.local]] - [set_name, [avatar.driver.local]]
@ -28,7 +28,7 @@ services:
arguments: arguments:
- @config - @config
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
- @cache.driver - @cache.driver
calls: calls:
- [set_name, [avatar.driver.remote]] - [set_name, [avatar.driver.remote]]
@ -40,7 +40,7 @@ services:
arguments: arguments:
- @config - @config
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
- @cache.driver - @cache.driver
calls: calls:
- [set_name, [avatar.driver.upload]] - [set_name, [avatar.driver.upload]]

View file

@ -36,7 +36,7 @@ services:
arguments: arguments:
- phpbb_ - phpbb_
- %core.root_path%includes/ - %core.root_path%includes/
- .%core.php_ext% - %core.php_ext%
calls: calls:
- [register, []] - [register, []]
- [set_cache, [@cache.driver]] - [set_cache, [@cache.driver]]
@ -46,7 +46,7 @@ services:
arguments: arguments:
- phpbb_ext_ - phpbb_ext_
- %core.root_path%ext/ - %core.root_path%ext/
- .%core.php_ext% - %core.php_ext%
calls: calls:
- [register, []] - [register, []]
- [set_cache, [@cache.driver]] - [set_cache, [@cache.driver]]
@ -70,7 +70,7 @@ services:
- @template - @template
- @user - @user
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
controller.resolver: controller.resolver:
class: phpbb_controller_resolver class: phpbb_controller_resolver
@ -131,20 +131,25 @@ services:
- @dbal.conn - @dbal.conn
- @config - @config
- @migrator - @migrator
- @filesystem
- %tables.ext% - %tables.ext%
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
- @cache.driver - @cache.driver
ext.finder: ext.finder:
class: phpbb_extension_finder class: phpbb_extension_finder
arguments: arguments:
- @ext.manager - @ext.manager
- @filesystem
- %core.root_path% - %core.root_path%
- @cache.driver - @cache.driver
- .%core.php_ext% - %core.php_ext%
- _ext_finder - _ext_finder
filesystem:
class: phpbb_filesystem
groupposition.legend: groupposition.legend:
class: phpbb_groupposition_legend class: phpbb_groupposition_legend
arguments: arguments:
@ -168,7 +173,7 @@ services:
class: phpbb_hook_finder class: phpbb_hook_finder
arguments: arguments:
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
- @cache.driver - @cache.driver
kernel_request_subscriber: kernel_request_subscriber:
@ -176,7 +181,7 @@ services:
arguments: arguments:
- @ext.finder - @ext.finder
- %core.root_path% - %core.root_path%
- .%core.php_ext% - %core.php_ext%
tags: tags:
- { name: kernel.event_subscriber } - { name: kernel.event_subscriber }
@ -242,6 +247,7 @@ services:
arguments: arguments:
- @ext.manager - @ext.manager
- @style.path_provider - @style.path_provider
- %core.root_path%
style.path_provider: style.path_provider:
class: phpbb_style_path_provider class: phpbb_style_path_provider

View file

@ -1060,6 +1060,8 @@ $action_ary = request_var('action', array('' =&gt; 0));
<h4>Login checks/redirection: </h4> <h4>Login checks/redirection: </h4>
<p>To show a forum login box use <code>login_forum_box($forum_data)</code>, else use the <code>login_box()</code> function.</p> <p>To show a forum login box use <code>login_forum_box($forum_data)</code>, else use the <code>login_box()</code> function.</p>
<p><code>$forum_data</code> should contain at least the <code>forum_id</code> and <code>forum_password</code> fields. If the field <code>forum_name</code> is available, then it is displayed on the forum login page.</p>
<p>The <code>login_box()</code> function can have a redirect as the first parameter. As a thumb of rule, specify an empty string if you want to redirect to the users current location, else do not add the <code>$SID</code> to the redirect string (for example within the ucp/login we redirect to the board index because else the user would be redirected to the login screen).</p> <p>The <code>login_box()</code> function can have a redirect as the first parameter. As a thumb of rule, specify an empty string if you want to redirect to the users current location, else do not add the <code>$SID</code> to the redirect string (for example within the ucp/login we redirect to the board index because else the user would be redirected to the login screen).</p>
<h4>Sensitive Operations: </h4> <h4>Sensitive Operations: </h4>
@ -2490,7 +2492,7 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
<hr /> <hr />
<a name="disclaimer"></a><h2>8. Copyright and disclaimer</h2> <a name="disclaimer"></a><h2>7. Copyright and disclaimer</h2>
<div class="paragraph"> <div class="paragraph">
<div class="inner"><span class="corners-top"><span></span></span> <div class="inner"><span class="corners-top"><span></span></span>

View file

@ -124,6 +124,15 @@ viewtopic_print_head_append
* Location: styles/prosilver/template/viewtopic_print.html * Location: styles/prosilver/template/viewtopic_print.html
* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen * Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen
viewtopic_body_footer_before
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
+ styles/subsilver2/template/viewtopic_body.html
* Purpose: Add content to the bottom of the View topic screen below the posts
and quick reply, directly before the jumpbox in Prosilver, breadcrumbs in
Subsilver2.
viewtopic_topic_title_prepend viewtopic_topic_title_prepend
=== ===
* Locations: * Locations:

View file

@ -50,9 +50,9 @@ if (isset($_GET['avatar']))
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
// Setup class loader first // Setup class loader first
$phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); $phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", $phpEx);
$phpbb_class_loader->register(); $phpbb_class_loader->register();
$phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", ".$phpEx"); $phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", $phpEx);
$phpbb_class_loader_ext->register(); $phpbb_class_loader_ext->register();
// Set up container // Set up container

View file

@ -55,6 +55,7 @@ class acp_board
'site_desc' => array('lang' => 'SITE_DESC', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false), 'site_desc' => array('lang' => 'SITE_DESC', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false),
'site_home_url' => array('lang' => 'SITE_HOME_URL', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true), 'site_home_url' => array('lang' => 'SITE_HOME_URL', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
'site_home_text' => array('lang' => 'SITE_HOME_TEXT', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true), 'site_home_text' => array('lang' => 'SITE_HOME_TEXT', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
'board_index_text' => array('lang' => 'BOARD_INDEX_TEXT', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
'board_disable' => array('lang' => 'DISABLE_BOARD', 'validate' => 'bool', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true), 'board_disable' => array('lang' => 'DISABLE_BOARD', 'validate' => 'bool', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true),
'board_disable_msg' => false, 'board_disable_msg' => false,
'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'validate' => 'lang', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false), 'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'validate' => 'lang', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false),
@ -397,6 +398,7 @@ class acp_board
'vars' => array( 'vars' => array(
'legend1' => 'ACP_SECURITY_SETTINGS', 'legend1' => 'ACP_SECURITY_SETTINGS',
'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_password_reset' => array('lang' => 'ALLOW_PASSWORD_RESET', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
'ip_check' => array('lang' => 'IP_VALID', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true), 'ip_check' => array('lang' => 'IP_VALID', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true),
'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),

View file

@ -54,7 +54,7 @@ class acp_extensions
// If they've specified an extension, let's load the metadata manager and validate it. // If they've specified an extension, let's load the metadata manager and validate it.
if ($ext_name) if ($ext_name)
{ {
$md_manager = new phpbb_extension_metadata_manager($ext_name, $db, $phpbb_extension_manager, $phpbb_root_path, ".$phpEx", $template, $config); $md_manager = new phpbb_extension_metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $phpbb_root_path);
try try
{ {
@ -81,7 +81,7 @@ class acp_extensions
case 'enable_pre': case 'enable_pre':
if (!$md_manager->validate_enable()) if (!$md_manager->validate_enable())
{ {
trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action)); trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING);
} }
if ($phpbb_extension_manager->enabled($ext_name)) if ($phpbb_extension_manager->enabled($ext_name))
@ -100,7 +100,7 @@ class acp_extensions
case 'enable': case 'enable':
if (!$md_manager->validate_enable()) if (!$md_manager->validate_enable())
{ {
trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action)); trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING);
} }
try try

View file

@ -148,57 +148,58 @@ class acp_groups
'action' => $action)) 'action' => $action))
); );
} }
break;
case 'set_default_on_all':
if (confirm_box(true))
{
$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
$start = 0;
do
{
$sql = 'SELECT user_id
FROM ' . USER_GROUP_TABLE . "
WHERE group_id = $group_id
ORDER BY user_id";
$result = $db->sql_query_limit($sql, 200, $start);
$mark_ary = array();
if ($row = $db->sql_fetchrow($result))
{
do
{
$mark_ary[] = $row['user_id'];
}
while ($row = $db->sql_fetchrow($result));
group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row);
$start = (sizeof($mark_ary) < 200) ? 0 : $start + 200;
}
else
{
$start = 0;
}
$db->sql_freeresult($result);
}
while ($start);
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
}
break; break;
case 'set_default_on_all':
if (confirm_box(true))
{
$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
$start = 0;
do
{
$sql = 'SELECT user_id
FROM ' . USER_GROUP_TABLE . "
WHERE group_id = $group_id
ORDER BY user_id";
$result = $db->sql_query_limit($sql, 200, $start);
$mark_ary = array();
if ($row = $db->sql_fetchrow($result))
{
do
{
$mark_ary[] = $row['user_id'];
}
while ($row = $db->sql_fetchrow($result));
group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row);
$start = (sizeof($mark_ary) < 200) ? 0 : $start + 200;
}
else
{
$start = 0;
}
$db->sql_freeresult($result);
}
while ($start);
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
}
break;
case 'deleteusers': case 'deleteusers':
if (empty($mark_ary)) if (empty($mark_ary))
{ {

View file

@ -115,7 +115,7 @@ class acp_inactive
{ {
$messenger->template('admin_welcome_activated', $row['user_lang']); $messenger->template('admin_welcome_activated', $row['user_lang']);
$messenger->to($row['user_email'], $row['username']); $messenger->set_addresses($row);
$messenger->anti_abuse_headers($config, $user); $messenger->anti_abuse_headers($config, $user);
@ -203,8 +203,7 @@ class acp_inactive
{ {
$messenger->template('user_remind_inactive', $row['user_lang']); $messenger->template('user_remind_inactive', $row['user_lang']);
$messenger->to($row['user_email'], $row['username']); $messenger->set_addresses($row);
$messenger->im($row['user_jabber'], $row['username']);
$messenger->anti_abuse_headers($config, $user); $messenger->anti_abuse_headers($config, $user);

View file

@ -331,7 +331,7 @@ class acp_prune
$s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>'; $s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>';
} }
$s_group_list = ''; $s_group_list = '<option value="0"></option>';
$sql = 'SELECT group_id, group_name $sql = 'SELECT group_id, group_name
FROM ' . GROUPS_TABLE . ' FROM ' . GROUPS_TABLE . '
WHERE group_type <> ' . GROUP_SPECIAL . ' WHERE group_type <> ' . GROUP_SPECIAL . '
@ -340,7 +340,7 @@ class acp_prune
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
$s_group_list .= '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</select>'; $s_group_list .= '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</option>';
} }
$db->sql_freeresult($result); $db->sql_freeresult($result);
@ -491,11 +491,12 @@ class acp_prune
if ($group_id) if ($group_id)
{ {
$sql = 'SELECT user_id $sql = 'SELECT u.user_id, u.username
FROM ' . USER_GROUP_TABLE . ' FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u
WHERE group_id = ' . (int) $group_id . ' WHERE ug.group_id = ' . (int) $group_id . '
AND user_pending = 0 AND ug.user_pending = 0
AND ' . $db->sql_in_set('user_id', $user_ids, false, true); AND ' . $db->sql_in_set('ug.user_id', $user_ids, false, true) . '
AND u.user_id = ug.user_id';
$result = $db->sql_query($sql); $result = $db->sql_query($sql);
// we're performing an intersection operation, so all the relevant users // we're performing an intersection operation, so all the relevant users
@ -504,24 +505,19 @@ class acp_prune
$user_ids = $usernames = array(); $user_ids = $usernames = array();
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
$user_ids[] = $row['poster_id']; $user_ids[] = $row['user_id'];
$usernames[$row['user_id']] = $row['username'];
} }
$db->sql_freeresult($result); $db->sql_freeresult($result);
// only get usernames if they are needed (not part of some later query)
if (!$posts_on_queue)
{
// this is an additional query aginst the users table
user_get_id_name($user_ids, $usernames);
}
} }
if ($posts_on_queue) if ($posts_on_queue)
{ {
$sql = 'SELECT poster_id, COUNT(post_id) AS queue_posts $sql = 'SELECT u.user_id, u.username, COUNT(p.post_id) AS queue_posts
FROM ' . POSTS_TABLE . ' FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
WHERE ' . $db->sql_in_set('poster_id', $user_ids, false, true) . ' WHERE ' . $db->sql_in_set('p.poster_id', $user_ids, false, true) . '
GROUP BY poster_id AND u.user_id = p.poster_id
GROUP BY p.poster_id
HAVING queue_posts ' . $key_match[$queue_select] . ' ' . $posts_on_queue; HAVING queue_posts ' . $key_match[$queue_select] . ' ' . $posts_on_queue;
$result = $db->sql_query($result); $result = $db->sql_query($result);
@ -529,12 +525,10 @@ class acp_prune
$user_ids = $usernames = array(); $user_ids = $usernames = array();
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
$user_ids[] = $row['poster_id']; $user_ids[] = $row['user_id'];
$usernames[$row['user_id']] = $row['username'];
} }
$db->sql_freeresult($result); $db->sql_freeresult($result);
// do an additional query to get the correct set of usernames
user_get_id_name($user_ids, $usernames);
} }
} }
} }

View file

@ -347,7 +347,7 @@ class acp_users
$messenger->template($email_template, $user_row['user_lang']); $messenger->template($email_template, $user_row['user_lang']);
$messenger->to($user_row['user_email'], $user_row['username']); $messenger->set_addresses($user_row);
$messenger->anti_abuse_headers($config, $user); $messenger->anti_abuse_headers($config, $user);
@ -402,7 +402,7 @@ class acp_users
$messenger->template('admin_welcome_activated', $user_row['user_lang']); $messenger->template('admin_welcome_activated', $user_row['user_lang']);
$messenger->to($user_row['user_email'], $user_row['username']); $messenger->set_addresses($user_row);
$messenger->anti_abuse_headers($config, $user); $messenger->anti_abuse_headers($config, $user);

View file

@ -74,7 +74,7 @@ class phpbb_avatar_driver_gravatar extends phpbb_avatar_driver
if (!function_exists('validate_data')) if (!function_exists('validate_data'))
{ {
require($this->phpbb_root_path . 'includes/functions_user' . $this->php_ext); require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
} }
$validate_array = validate_data( $validate_array = validate_data(

View file

@ -63,7 +63,7 @@ class phpbb_avatar_driver_remote extends phpbb_avatar_driver
if (!function_exists('validate_data')) if (!function_exists('validate_data'))
{ {
require($this->phpbb_root_path . 'includes/functions_user' . $this->php_ext); require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
} }
$validate_array = validate_data( $validate_array = validate_data(
@ -117,7 +117,7 @@ class phpbb_avatar_driver_remote extends phpbb_avatar_driver
if (!class_exists('fileupload')) if (!class_exists('fileupload'))
{ {
include($this->phpbb_root_path . 'includes/functions_upload' . $this->php_ext); include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext);
} }
$types = fileupload::image_types(); $types = fileupload::image_types();

View file

@ -27,7 +27,7 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver
public function get_data($row, $ignore_config = false) public function get_data($row, $ignore_config = false)
{ {
return array( return array(
'src' => $this->phpbb_root_path . 'download/file' . $this->php_ext . '?avatar=' . $row['avatar'], 'src' => $this->phpbb_root_path . 'download/file.' . $this->php_ext . '?avatar=' . $row['avatar'],
'width' => $row['avatar_width'], 'width' => $row['avatar_width'],
'height' => $row['avatar_height'], 'height' => $row['avatar_height'],
); );
@ -63,7 +63,7 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver
if (!class_exists('fileupload')) if (!class_exists('fileupload'))
{ {
include($this->phpbb_root_path . 'includes/functions_upload' . $this->php_ext); include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext);
} }
$upload = new fileupload('AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); $upload = new fileupload('AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false));

View file

@ -133,7 +133,7 @@ class bbcode
$this->template_bitfield = new bitfield($user->style['bbcode_bitfield']); $this->template_bitfield = new bitfield($user->style['bbcode_bitfield']);
$style_resource_locator = new phpbb_style_resource_locator(); $style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider()); $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider(), $phpbb_root_path);
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager); $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template); $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template);
$style->set_style(); $style->set_style();

View file

@ -270,7 +270,7 @@ class phpbb_recaptcha extends phpbb_default_captcha
$response = ''; $response = '';
if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10))) if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10)))
{ {
trigger_error('Could not open socket', E_USER_ERROR); trigger_error('RECAPTCHA_SOCKET_ERROR', E_USER_ERROR);
} }
fwrite($fs, $http_request); fwrite($fs, $http_request);

View file

@ -52,7 +52,7 @@ class phpbb_class_loader
* @param string $php_ext The file extension for PHP files * @param string $php_ext The file extension for PHP files
* @param phpbb_cache_driver_interface $cache An implementation of the phpBB cache interface. * @param phpbb_cache_driver_interface $cache An implementation of the phpBB cache interface.
*/ */
public function __construct($prefix, $path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null) public function __construct($prefix, $path, $php_ext = 'php', phpbb_cache_driver_interface $cache = null)
{ {
$this->prefix = $prefix; $this->prefix = $prefix;
$this->path = $path; $this->path = $path;
@ -111,7 +111,7 @@ class phpbb_class_loader
{ {
if (isset($this->cached_paths[$class])) if (isset($this->cached_paths[$class]))
{ {
return $this->path . $this->cached_paths[$class] . $this->php_ext; return $this->path . $this->cached_paths[$class] . '.' . $this->php_ext;
} }
if (!preg_match('/^' . $this->prefix . '[a-zA-Z0-9_]+$/', $class)) if (!preg_match('/^' . $this->prefix . '[a-zA-Z0-9_]+$/', $class))
@ -136,7 +136,7 @@ class phpbb_class_loader
$relative_path = $dirs . implode(array_slice($parts, $i, sizeof($parts) - $i), '_'); $relative_path = $dirs . implode(array_slice($parts, $i, sizeof($parts) - $i), '_');
if (!file_exists($this->path . $relative_path . $this->php_ext)) if (!file_exists($this->path . $relative_path . '.' . $this->php_ext))
{ {
return false; return false;
} }
@ -147,7 +147,7 @@ class phpbb_class_loader
$this->cache->put('class_loader_' . $this->prefix, $this->cached_paths); $this->cache->put('class_loader_' . $this->prefix, $this->cached_paths);
} }
return $this->path . $relative_path . $this->php_ext; return $this->path . $relative_path . '.' . $this->php_ext;
} }
/** /**

View file

@ -85,17 +85,39 @@ class phpbb_controller_helper
} }
/** /**
* Easily generate a URL * Generate a URL
* *
* @param array $url_parts Each array element is a 'folder' * @param string $route The route to travel
* i.e. array('my', 'ext') maps to ./app.php/my/ext * @param mixed $params String or array of additional url parameters
* @param mixed $query The Query string, passed directly into the second * @param bool $is_amp Is url using &amp; (true) or & (false)
* argument of append_sid() * @param string $session_id Possibility to use a custom session id instead of the global one
* @return string A URL that has already been run through append_sid() * @return string The URL already passed through append_sid()
*/ */
public function url(array $url_parts, $query = '') public function url($route, $params = false, $is_amp = true, $session_id = false)
{ {
return append_sid($this->phpbb_root_path . implode('/', $url_parts), $query); $route_params = '';
if (($route_delim = strpos($route, '?')) !== false)
{
$route_params = substr($route, $route_delim);
$route = substr($route, 0, $route_delim);
}
if (is_array($params) && !empty($params))
{
$params = array_merge(array(
'controller' => $route,
), $params);
}
else if (is_string($params) && $params)
{
$params = 'controller=' . $route . (($is_amp) ? '&amp;' : '&') . $params;
}
else
{
$params = array('controller' => $route);
}
return append_sid($this->phpbb_root_path . 'app.' . $this->php_ext . $route_params, $params, $is_amp, $session_id);
} }
/** /**

View file

@ -568,12 +568,12 @@ class phpbb_db_driver
* Run more than one insert statement. * Run more than one insert statement.
* *
* @param string $table table name to run the statements on * @param string $table table name to run the statements on
* @param array &$sql_ary multi-dimensional array holding the statement data. * @param array $sql_ary multi-dimensional array holding the statement data.
* *
* @return bool false if no statements were executed. * @return bool false if no statements were executed.
* @access public * @access public
*/ */
function sql_multi_insert($table, &$sql_ary) function sql_multi_insert($table, $sql_ary)
{ {
if (!sizeof($sql_ary)) if (!sizeof($sql_ary))
{ {

View file

@ -0,0 +1,65 @@
<?php
/**
*
* @package dbal
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* MSSQL Database Base Abstraction Layer
* @package dbal
*/
abstract class phpbb_db_driver_mssql_base extends phpbb_db_driver
{
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' + ' . $expr2;
}
/**
* Escape string used in sql query
*/
function sql_escape($msg)
{
return str_replace(array("'", "\0"), array("''", ''), $msg);
}
/**
* {@inheritDoc}
*/
function sql_lower_text($column_name)
{
return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))";
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
return $data;
}
}

View file

@ -26,7 +26,7 @@ if (!defined('IN_PHPBB'))
* *
* @package dbal * @package dbal
*/ */
class phpbb_db_driver_mssql_odbc extends phpbb_db_driver class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base
{ {
var $last_query_text = ''; var $last_query_text = '';
var $connect_error = ''; var $connect_error = '';
@ -125,14 +125,6 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver
return ($this->sql_server_version) ? 'MSSQL (ODBC)<br />' . $this->sql_server_version : 'MSSQL (ODBC)'; return ($this->sql_server_version) ? 'MSSQL (ODBC)<br />' . $this->sql_server_version : 'MSSQL (ODBC)';
} }
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' + ' . $expr2;
}
/** /**
* SQL Transaction * SQL Transaction
* @access private * @access private
@ -325,40 +317,6 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver
return false; return false;
} }
/**
* Escape string used in sql query
*/
function sql_escape($msg)
{
return str_replace(array("'", "\0"), array("''", ''), $msg);
}
/**
* {@inheritDoc}
*/
function sql_lower_text($column_name)
{
return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))";
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
return $data;
}
/** /**
* return sql error array * return sql error array
* @access private * @access private

View file

@ -191,7 +191,7 @@ class result_mssqlnative
/** /**
* @package dbal * @package dbal
*/ */
class phpbb_db_driver_mssqlnative extends phpbb_db_driver class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base
{ {
var $m_insert_id = NULL; var $m_insert_id = NULL;
var $last_query_text = ''; var $last_query_text = '';
@ -256,14 +256,6 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver
return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL'; return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL';
} }
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' + ' . $expr2;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -490,31 +482,6 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver
return false; return false;
} }
/**
* Escape string used in sql query
*/
function sql_escape($msg)
{
return str_replace(array("'", "\0"), array("''", ''), $msg);
}
/**
* {@inheritDoc}
*/
function sql_lower_text($column_name)
{
return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))";
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
/** /**
* return sql error array * return sql error array
* @access private * @access private
@ -560,15 +527,6 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver
return $error; return $error;
} }
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
return $data;
}
/** /**
* Close sql connection * Close sql connection
* @access private * @access private

View file

@ -24,7 +24,7 @@ if (!defined('IN_PHPBB'))
* MySQL 5.0+ * MySQL 5.0+
* @package dbal * @package dbal
*/ */
class phpbb_db_driver_mysql extends phpbb_db_driver class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base
{ {
var $multi_insert = true; var $multi_insert = true;
var $connect_error = ''; var $connect_error = '';
@ -135,14 +135,6 @@ class phpbb_db_driver_mysql extends phpbb_db_driver
return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version; return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version;
} }
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return 'CONCAT(' . $expr1 . ', ' . $expr2 . ')';
}
/** /**
* SQL Transaction * SQL Transaction
* @access private * @access private
@ -226,25 +218,6 @@ class phpbb_db_driver_mysql extends phpbb_db_driver
return $this->query_result; return $this->query_result;
} }
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// if $total is set to 0 we do not want to limit the number of rows
if ($total == 0)
{
// Having a value of -1 was always a bug
$total = '18446744073709551615';
}
$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
return $this->sql_query($query, $cache_ttl);
}
/** /**
* Return number of affected rows * Return number of affected rows
*/ */
@ -341,101 +314,6 @@ class phpbb_db_driver_mysql extends phpbb_db_driver
return @mysql_real_escape_string($msg, $this->db_connect_id); return @mysql_real_escape_string($msg, $this->db_connect_id);
} }
/**
* Gets the estimated number of rows in a specified table.
*
* @param string $table_name Table name
*
* @return string Number of rows in $table_name.
* Prefixed with ~ if estimated (otherwise exact).
*
* @access public
*/
function get_estimated_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']))
{
if ($table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000)
{
return '~' . $table_status['Rows'];
}
}
return parent::get_row_count($table_name);
}
/**
* Gets the exact number of rows in a specified table.
*
* @param string $table_name Table name
*
* @return string Exact number of rows in $table_name.
*
* @access public
*/
function get_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
return parent::get_row_count($table_name);
}
/**
* Gets some information about the specified table.
*
* @param string $table_name Table name
*
* @return array
*
* @access protected
*/
function get_table_status($table_name)
{
$sql = "SHOW TABLE STATUS
LIKE '" . $this->sql_escape($table_name) . "'";
$result = $this->sql_query($sql);
$table_status = $this->sql_fetchrow($result);
$this->sql_freeresult($result);
return $table_status;
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
switch ($stage)
{
case 'FROM':
$data = '(' . $data . ')';
break;
}
return $data;
}
/** /**
* return sql error array * return sql error array
* @access private * @access private

View file

@ -0,0 +1,145 @@
<?php
/**
*
* @package dbal
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Abstract MySQL Database Base Abstraction Layer
* @package dbal
*/
abstract class phpbb_db_driver_mysql_base extends phpbb_db_driver
{
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return 'CONCAT(' . $expr1 . ', ' . $expr2 . ')';
}
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// if $total is set to 0 we do not want to limit the number of rows
if ($total == 0)
{
// MySQL 4.1+ no longer supports -1 in limit queries
$total = '18446744073709551615';
}
$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
return $this->sql_query($query, $cache_ttl);
}
/**
* Gets the estimated number of rows in a specified table.
*
* @param string $table_name Table name
*
* @return string Number of rows in $table_name.
* Prefixed with ~ if estimated (otherwise exact).
*
* @access public
*/
function get_estimated_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']))
{
if ($table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000)
{
return '~' . $table_status['Rows'];
}
}
return parent::get_row_count($table_name);
}
/**
* Gets the exact number of rows in a specified table.
*
* @param string $table_name Table name
*
* @return string Exact number of rows in $table_name.
*
* @access public
*/
function get_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
return parent::get_row_count($table_name);
}
/**
* Gets some information about the specified table.
*
* @param string $table_name Table name
*
* @return array
*
* @access protected
*/
function get_table_status($table_name)
{
$sql = "SHOW TABLE STATUS
LIKE '" . $this->sql_escape($table_name) . "'";
$result = $this->sql_query($sql);
$table_status = $this->sql_fetchrow($result);
$this->sql_freeresult($result);
return $table_status;
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
switch ($stage)
{
case 'FROM':
$data = '(' . $data . ')';
break;
}
return $data;
}
}

View file

@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
* MySQL 4.1+ or MySQL 5.0+ * MySQL 4.1+ or MySQL 5.0+
* @package dbal * @package dbal
*/ */
class phpbb_db_driver_mysqli extends phpbb_db_driver class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base
{ {
var $multi_insert = true; var $multi_insert = true;
var $connect_error = ''; var $connect_error = '';
@ -103,6 +103,7 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver
/** /**
* Version information about used database * Version information about used database
* @param bool $raw if true, only return the fetched sql_server_version
* @param bool $use_cache If true, it is safe to retrieve the value from the cache * @param bool $use_cache If true, it is safe to retrieve the value from the cache
* @return string sql server version * @return string sql server version
*/ */
@ -127,14 +128,6 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver
return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version; return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version;
} }
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return 'CONCAT(' . $expr1 . ', ' . $expr2 . ')';
}
/** /**
* SQL Transaction * SQL Transaction
* @access private * @access private
@ -217,25 +210,6 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver
return $this->query_result; return $this->query_result;
} }
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// if $total is set to 0 we do not want to limit the number of rows
if ($total == 0)
{
// MySQL 4.1+ no longer supports -1 in limit queries
$total = '18446744073709551615';
}
$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
return $this->sql_query($query, $cache_ttl);
}
/** /**
* Return number of affected rows * Return number of affected rows
*/ */
@ -327,101 +301,6 @@ class phpbb_db_driver_mysqli extends phpbb_db_driver
return @mysqli_real_escape_string($this->db_connect_id, $msg); return @mysqli_real_escape_string($this->db_connect_id, $msg);
} }
/**
* Gets the estimated number of rows in a specified table.
*
* @param string $table_name Table name
*
* @return string Number of rows in $table_name.
* Prefixed with ~ if estimated (otherwise exact).
*
* @access public
*/
function get_estimated_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']))
{
if ($table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000)
{
return '~' . $table_status['Rows'];
}
}
return parent::get_row_count($table_name);
}
/**
* Gets the exact number of rows in a specified table.
*
* @param string $table_name Table name
*
* @return string Exact number of rows in $table_name.
*
* @access public
*/
function get_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
return parent::get_row_count($table_name);
}
/**
* Gets some information about the specified table.
*
* @param string $table_name Table name
*
* @return array
*
* @access protected
*/
function get_table_status($table_name)
{
$sql = "SHOW TABLE STATUS
LIKE '" . $this->sql_escape($table_name) . "'";
$result = $this->sql_query($sql);
$table_status = $this->sql_fetchrow($result);
$this->sql_freeresult($result);
return $table_status;
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
switch ($stage)
{
case 'FROM':
$data = '(' . $data . ')';
break;
}
return $data;
}
/** /**
* return sql error array * return sql error array
* @access private * @access private

View file

@ -0,0 +1,23 @@
<?php
/**
*
* @package migration
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_boardindex extends phpbb_db_migration
{
public function effectively_installed()
{
return isset($this->config['board_index_text']);
}
public function update_data()
{
return array(
array('config.add', array('board_index_text', '')),
);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_forgot_password extends phpbb_db_migration
{
public function effectively_installed()
{
return isset($this->config['allow_password_reset']);
}
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_11');
}
public function update_data()
{
return array(
array('config.add', array('allow_password_reset', 1)),
);
}
}

View file

@ -0,0 +1,31 @@
<?php
/**
*
* @package migration
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
class phpbb_db_migration_data_310_jquery_update extends phpbb_db_migration
{
public function effectively_installed()
{
return $this->config['load_jquery_url'] !== '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js';
}
static public function depends_on()
{
return array(
'phpbb_db_migration_data_310_dev',
);
}
public function update_data()
{
return array(
array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js')),
);
}
}

View file

@ -19,6 +19,34 @@ class phpbb_db_migration_data_310_style_update_p1 extends phpbb_db_migration
return array('phpbb_db_migration_data_30x_3_0_11'); return array('phpbb_db_migration_data_30x_3_0_11');
} }
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'styles' => array(
'style_path' => array('VCHAR:100', ''),
'bbcode_bitfield' => array('VCHAR:255', 'kNg='),
'style_parent_id' => array('UINT', 0),
'style_parent_tree' => array('TEXT', ''),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'styles' => array(
'style_path',
'bbcode_bitfield',
'style_parent_id',
'style_parent_tree',
),
),
);
}
public function update_data() public function update_data()
{ {
return array( return array(

View file

@ -0,0 +1,150 @@
<?php
/**
*
* @package dbal
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Collects rows for insert into a database until the buffer size is reached.
* Then flushes the buffer to the database and starts over again.
*
* Benefits over collecting a (possibly huge) insert array and then using
* $db->sql_multi_insert() include:
*
* - Going over max packet size of the database connection is usually prevented
* because the data is submitted in batches.
*
* - Reaching database connection timeout is usually prevented because
* submission of batches talks to the database every now and then.
*
* - Usage of less PHP memory because data no longer needed is discarded on
* buffer flush.
*
* Attention:
* Please note that users of this class have to call flush() to flush the
* remaining rows to the database after their batch insert operation is
* finished.
*
* Usage:
* <code>
* $buffer = new phpbb_db_sql_insert_buffer($db, 'test_table', 1234);
*
* while (do_stuff())
* {
* $buffer->insert(array(
* 'column1' => 'value1',
* 'column2' => 'value2',
* ));
* }
*
* $buffer->flush();
* </code>
*
* @package dbal
*/
class phpbb_db_sql_insert_buffer
{
/** @var phpbb_db_driver */
protected $db;
/** @var string */
protected $table_name;
/** @var int */
protected $max_buffered_rows;
/** @var array */
protected $buffer = array();
/**
* @param phpbb_db_driver $db
* @param string $table_name
* @param int $max_buffered_rows
*/
public function __construct(phpbb_db_driver $db, $table_name, $max_buffered_rows = 500)
{
$this->db = $db;
$this->table_name = $table_name;
$this->max_buffered_rows = $max_buffered_rows;
}
/**
* Inserts a single row into the buffer if multi insert is supported by the
* database (otherwise an insert query is sent immediately). Then flushes
* the buffer if the number of rows in the buffer is now greater than or
* equal to $max_buffered_rows.
*
* @param array $row
*
* @return bool True when some data was flushed to the database.
* False otherwise.
*/
public function insert(array $row)
{
$this->buffer[] = $row;
// Flush buffer if it is full or when DB does not support multi inserts.
// In the later case, the buffer will always only contain one row.
if (!$this->db->multi_insert || sizeof($this->buffer) >= $this->max_buffered_rows)
{
return $this->flush();
}
return false;
}
/**
* Inserts a row set, i.e. an array of rows, by calling insert().
*
* Please note that it is in most cases better to use insert() instead of
* first building a huge rowset. Or at least sizeof($rows) should be kept
* small.
*
* @param array $rows
*
* @return bool True when some data was flushed to the database.
* False otherwise.
*/
public function insert_all(array $rows)
{
// Using bitwise |= because PHP does not have logical ||=
$result = 0;
foreach ($rows as $row)
{
$result |= (int) $this->insert($row);
}
return (bool) $result;
}
/**
* Flushes the buffer content to the DB and clears the buffer.
*
* @return bool True when some data was flushed to the database.
* False otherwise.
*/
public function flush()
{
if (!empty($this->buffer))
{
$this->db->sql_multi_insert($this->table_name, $this->buffer);
$this->buffer = array();
return true;
}
return false;
}
}

View file

@ -23,6 +23,7 @@ if (!defined('IN_PHPBB'))
class phpbb_extension_finder class phpbb_extension_finder
{ {
protected $extension_manager; protected $extension_manager;
protected $filesystem;
protected $phpbb_root_path; protected $phpbb_root_path;
protected $cache; protected $cache;
protected $php_ext; protected $php_ext;
@ -54,15 +55,17 @@ class phpbb_extension_finder
* @param phpbb_extension_manager $extension_manager An extension manager * @param phpbb_extension_manager $extension_manager An extension manager
* instance that provides the finder with a list of active * instance that provides the finder with a list of active
* extensions and their locations * extensions and their locations
* @param phpbb_filesystem $filesystem Filesystem instance
* @param string $phpbb_root_path Path to the phpbb root directory * @param string $phpbb_root_path Path to the phpbb root directory
* @param phpbb_cache_driver_interface $cache A cache instance or null * @param phpbb_cache_driver_interface $cache A cache instance or null
* @param string $php_ext php file extension * @param string $php_ext php file extension
* @param string $cache_name The name of the cache variable, defaults to * @param string $cache_name The name of the cache variable, defaults to
* _ext_finder * _ext_finder
*/ */
public function __construct(phpbb_extension_manager $extension_manager, $phpbb_root_path = '', phpbb_cache_driver_interface $cache = null, $php_ext = '.php', $cache_name = '_ext_finder') public function __construct(phpbb_extension_manager $extension_manager, phpbb_filesystem $filesystem, $phpbb_root_path = '', phpbb_cache_driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder')
{ {
$this->extension_manager = $extension_manager; $this->extension_manager = $extension_manager;
$this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
$this->cache = $cache; $this->cache = $cache;
$this->php_ext = $php_ext; $this->php_ext = $php_ext;
@ -227,7 +230,7 @@ class phpbb_extension_finder
*/ */
protected function sanitise_directory($directory) protected function sanitise_directory($directory)
{ {
$directory = preg_replace('#(?:^|/)\./#', '/', $directory); $directory = $this->filesystem->clean_path($directory);
$dir_len = strlen($directory); $dir_len = strlen($directory);
if ($dir_len > 1 && $directory[$dir_len - 1] === '/') if ($dir_len > 1 && $directory[$dir_len - 1] === '/')
@ -253,8 +256,8 @@ class phpbb_extension_finder
*/ */
public function get_classes($cache = true, $use_all_available = false) public function get_classes($cache = true, $use_all_available = false)
{ {
$this->query['extension_suffix'] .= $this->php_ext; $this->query['extension_suffix'] .= '.' . $this->php_ext;
$this->query['core_suffix'] .= $this->php_ext; $this->query['core_suffix'] .= '.' . $this->php_ext;
$files = $this->find($cache, false, $use_all_available); $files = $this->find($cache, false, $use_all_available);
@ -274,7 +277,7 @@ class phpbb_extension_finder
{ {
$file = preg_replace('#^includes/#', '', $file); $file = preg_replace('#^includes/#', '', $file);
$classes[] = 'phpbb_' . str_replace('/', '_', substr($file, 0, -strlen($this->php_ext))); $classes[] = 'phpbb_' . str_replace('/', '_', substr($file, 0, -strlen('.' . $this->php_ext)));
} }
return $classes; return $classes;
} }

View file

@ -44,13 +44,14 @@ class phpbb_extension_manager
* @param phpbb_db_driver $db A database connection * @param phpbb_db_driver $db A database connection
* @param phpbb_config $config phpbb_config * @param phpbb_config $config phpbb_config
* @param phpbb_db_migrator $migrator * @param phpbb_db_migrator $migrator
* @param phpbb_filesystem $filesystem
* @param string $extension_table The name of the table holding extensions * @param string $extension_table The name of the table holding extensions
* @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $phpbb_root_path Path to the phpbb includes directory.
* @param string $php_ext php file extension * @param string $php_ext php file extension
* @param phpbb_cache_driver_interface $cache A cache instance or null * @param phpbb_cache_driver_interface $cache A cache instance or null
* @param string $cache_name The name of the cache variable, defaults to _ext * @param string $cache_name The name of the cache variable, defaults to _ext
*/ */
public function __construct(ContainerInterface $container, phpbb_db_driver $db, phpbb_config $config, phpbb_db_migrator $migrator, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext') public function __construct(ContainerInterface $container, phpbb_db_driver $db, phpbb_config $config, phpbb_db_migrator $migrator, phpbb_filesystem $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext')
{ {
$this->container = $container; $this->container = $container;
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
@ -58,6 +59,7 @@ class phpbb_extension_manager
$this->config = $config; $this->config = $config;
$this->migrator = $migrator; $this->migrator = $migrator;
$this->cache = $cache; $this->cache = $cache;
$this->filesystem = $filesystem;
$this->php_ext = $php_ext; $this->php_ext = $php_ext;
$this->extension_table = $extension_table; $this->extension_table = $extension_table;
$this->cache_name = $cache_name; $this->cache_name = $cache_name;
@ -153,7 +155,7 @@ class phpbb_extension_manager
*/ */
public function create_extension_metadata_manager($name, phpbb_template $template) public function create_extension_metadata_manager($name, phpbb_template $template)
{ {
return new phpbb_extension_metadata_manager($name, $this->db, $this, $this->phpbb_root_path, $this->php_ext, $template, $this->config); return new phpbb_extension_metadata_manager($name, $this->config, $this, $template, $this->phpbb_root_path);
} }
/** /**
@ -410,7 +412,7 @@ class phpbb_extension_manager
RecursiveIteratorIterator::SELF_FIRST); RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file_info) foreach ($iterator as $file_info)
{ {
if ($file_info->isFile() && $file_info->getFilename() == 'ext' . $this->php_ext) if ($file_info->isFile() && $file_info->getFilename() == 'ext.' . $this->php_ext)
{ {
$ext_name = $iterator->getInnerIterator()->getSubPath(); $ext_name = $iterator->getInnerIterator()->getSubPath();
@ -510,7 +512,7 @@ class phpbb_extension_manager
*/ */
public function get_finder() public function get_finder()
{ {
return new phpbb_extension_finder($this, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder'); return new phpbb_extension_finder($this, $this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
} }
/** /**

View file

@ -22,31 +22,64 @@ if (!defined('IN_PHPBB'))
*/ */
class phpbb_extension_metadata_manager class phpbb_extension_metadata_manager
{ {
protected $phpEx; /**
* phpBB Config instance
* @var phpbb_config
*/
protected $config;
/**
* phpBB Extension Manager
* @var phpbb_extension_manager
*/
protected $extension_manager; protected $extension_manager;
protected $db;
protected $phpbb_root_path; /**
* phpBB Template instance
* @var phpbb_template
*/
protected $template; protected $template;
/**
* phpBB root path
* @var string
*/
protected $phpbb_root_path;
/**
* Name (including vendor) of the extension
* @var string
*/
protected $ext_name; protected $ext_name;
/**
* Metadata from the composer.json file
* @var array
*/
protected $metadata; protected $metadata;
/**
* Link (including root path) to the metadata file
* @var string
*/
protected $metadata_file; protected $metadata_file;
/** /**
* Creates the metadata manager * Creates the metadata manager
* *
* @param phpbb_db_driver $db A database connection * @param string $ext_name Name (including vendor) of the extension
* @param string $extension_manager An instance of the phpbb extension manager * @param phpbb_config $config phpBB Config instance
* @param string $phpbb_root_path Path to the phpbb includes directory. * @param phpbb_extension_manager $extension_manager An instance of the phpBBb extension manager
* @param string $phpEx php file extension * @param phpbb_template $template phpBB Template instance
* @param string $phpbb_root_path Path to the phpbb includes directory.
*/ */
public function __construct($ext_name, phpbb_db_driver $db, phpbb_extension_manager $extension_manager, $phpbb_root_path, $phpEx = '.php', phpbb_template $template, phpbb_config $config) public function __construct($ext_name, phpbb_config $config, phpbb_extension_manager $extension_manager, phpbb_template $template, $phpbb_root_path)
{ {
$this->phpbb_root_path = $phpbb_root_path;
$this->db = $db;
$this->config = $config; $this->config = $config;
$this->phpEx = $phpEx;
$this->template = $template;
$this->extension_manager = $extension_manager; $this->extension_manager = $extension_manager;
$this->template = $template;
$this->phpbb_root_path = $phpbb_root_path;
$this->ext_name = $ext_name; $this->ext_name = $ext_name;
$this->metadata = array(); $this->metadata = array();
$this->metadata_file = ''; $this->metadata_file = '';

View file

@ -0,0 +1,52 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* A class with various functions that are related to paths, files and the filesystem
* @package phpBB3
*/
class phpbb_filesystem
{
/**
* Eliminates useless . and .. components from specified path.
*
* @param string $path Path to clean
* @return string Cleaned path
*/
public function clean_path($path)
{
$exploded = explode('/', $path);
$filtered = array();
foreach ($exploded as $part)
{
if ($part === '.' && !empty($filtered))
{
continue;
}
if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '..')
{
array_pop($filtered);
}
else
{
$filtered[] = $part;
}
}
$path = implode('/', $filtered);
return $path;
}
}

View file

@ -1049,31 +1049,33 @@ else
/** /**
* Eliminates useless . and .. components from specified path. * Eliminates useless . and .. components from specified path.
* *
* Deprecated, use filesystem class instead
*
* @param string $path Path to clean * @param string $path Path to clean
* @return string Cleaned path * @return string Cleaned path
*
* @deprecated
*/ */
function phpbb_clean_path($path) function phpbb_clean_path($path)
{ {
$exploded = explode('/', $path); global $phpbb_container;
$filtered = array();
foreach ($exploded as $part)
{
if ($part === '.' && !empty($filtered))
{
continue;
}
if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '..') if ($phpbb_container)
{ {
array_pop($filtered); $phpbb_filesystem = $phpbb_container->get('filesystem');
}
else
{
$filtered[] = $part;
}
} }
$path = implode('/', $filtered); else
return $path; {
// The container is not yet loaded, use a new instance
if (!class_exists('phpbb_filesystem'))
{
global $phpbb_root_path, $phpEx;
require($phpbb_root_path . 'includes/filesystem.' . $phpEx);
}
$phpbb_filesystem = new phpbb_filesystem();
}
return $phpbb_filesystem->clean_path($path);
} }
// functions used for building option fields // functions used for building option fields
@ -2731,7 +2733,7 @@ function redirect($url, $return = false, $disable_cd_check = false)
// Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2 // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false) if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false)
{ {
trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR); trigger_error('INSECURE_REDIRECT', E_USER_ERROR);
} }
// Now, also check the protocol and for a valid url the last time... // Now, also check the protocol and for a valid url the last time...
@ -2740,7 +2742,7 @@ function redirect($url, $return = false, $disable_cd_check = false)
if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols)) if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols))
{ {
trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR); trigger_error('INSECURE_REDIRECT', E_USER_ERROR);
} }
if ($return) if ($return)
@ -3465,6 +3467,7 @@ function login_forum_box($forum_data)
page_header($user->lang['LOGIN'], false); page_header($user->lang['LOGIN'], false);
$template->assign_vars(array( $template->assign_vars(array(
'FORUM_NAME' => isset($forum_data['forum_name']) ? $forum_data['forum_name'] : '',
'S_LOGIN_ACTION' => build_url(array('f')), 'S_LOGIN_ACTION' => build_url(array('f')),
'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id']))) 'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id'])))
); );
@ -4182,7 +4185,7 @@ function phpbb_checkdnsrr($host, $type = 'MX')
// Handler, header and footer // Handler, header and footer
/** /**
* Error and message handler, call with trigger_error if reqd * Error and message handler, call with trigger_error if read
*/ */
function msg_handler($errno, $msg_text, $errfile, $errline) function msg_handler($errno, $msg_text, $errfile, $errline)
{ {
@ -5292,7 +5295,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'BOARD_URL' => $board_url, 'BOARD_URL' => $board_url,
'L_LOGIN_LOGOUT' => $l_login_logout, 'L_LOGIN_LOGOUT' => $l_login_logout,
'L_INDEX' => $user->lang['FORUM_INDEX'], 'L_INDEX' => ($config['board_index_text'] !== '') ? $config['board_index_text'] : $user->lang['FORUM_INDEX'],
'L_SITE_HOME' => ($config['site_home_text'] !== '') ? $config['site_home_text'] : $user->lang['HOME'], 'L_SITE_HOME' => ($config['site_home_text'] !== '') ? $config['site_home_text'] : $user->lang['HOME'],
'L_ONLINE_EXPLAIN' => $l_online_time, 'L_ONLINE_EXPLAIN' => $l_online_time,

View file

@ -625,7 +625,7 @@ function phpbb_increment_downloads($db, $ids)
*/ */
function phpbb_download_handle_forum_auth($db, $auth, $topic_id) function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
{ {
$sql = 'SELECT t.forum_id, f.forum_password, f.parent_id $sql = 'SELECT t.forum_id, f.forum_name, f.forum_password, f.parent_id
FROM ' . TOPICS_TABLE . ' t, ' . FORUMS_TABLE . " f FROM ' . TOPICS_TABLE . ' t, ' . FORUMS_TABLE . " f
WHERE t.topic_id = " . (int) $topic_id . " WHERE t.topic_id = " . (int) $topic_id . "
AND t.forum_id = f.forum_id"; AND t.forum_id = f.forum_id";

View file

@ -55,6 +55,24 @@ class messenger
$this->vars = $this->msg = $this->replyto = $this->from = ''; $this->vars = $this->msg = $this->replyto = $this->from = '';
$this->mail_priority = MAIL_NORMAL_PRIORITY; $this->mail_priority = MAIL_NORMAL_PRIORITY;
} }
/**
* Set addresses for to/im as available
*
* @param array $user User row
*/
function set_addresses($user)
{
if (isset($user['user_email']) && $user['user_email'])
{
$this->to($user['user_email'], (isset($user['username']) ? $user['username'] : ''));
}
if (isset($user['user_jabber']) && $user['user_jabber'])
{
$this->im($user['user_jabber'], (isset($user['username']) ? $user['username'] : ''));
}
}
/** /**
* Sets an email address to send to * Sets an email address to send to
@ -209,7 +227,7 @@ class messenger
if (!isset($this->tpl_msg[$template_lang . $template_file])) if (!isset($this->tpl_msg[$template_lang . $template_file]))
{ {
$style_resource_locator = new phpbb_style_resource_locator(); $style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider()); $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider(), $phpbb_root_path);
$tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager); $tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl); $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl);

View file

@ -60,7 +60,7 @@ function phpbb_create_dumped_url_matcher(phpbb_extension_finder $finder, $root_p
'class' => 'phpbb_url_matcher', 'class' => 'phpbb_url_matcher',
)); ));
file_put_contents($root_path . 'cache/url_matcher' . $php_ext, $cached_url_matcher_dump); file_put_contents($root_path . 'cache/url_matcher.' . $php_ext, $cached_url_matcher_dump);
} }
/** /**
@ -87,7 +87,7 @@ function phpbb_create_url_matcher(phpbb_extension_finder $finder, RequestContext
*/ */
function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext) function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext)
{ {
require($root_path . 'cache/url_matcher' . $php_ext); require($root_path . 'cache/url_matcher.' . $php_ext);
return new phpbb_url_matcher($context); return new phpbb_url_matcher($context);
} }
@ -102,5 +102,5 @@ function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext)
*/ */
function phpbb_url_matcher_dumped($root_path, $php_ext) function phpbb_url_matcher_dumped($root_path, $php_ext)
{ {
return file_exists($root_path . 'cache/url_matcher' . $php_ext); return file_exists($root_path . 'cache/url_matcher.' . $php_ext);
} }

View file

@ -2924,8 +2924,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
{ {
$messenger->template('group_approved', $row['user_lang']); $messenger->template('group_approved', $row['user_lang']);
$messenger->to($row['user_email'], $row['username']); $messenger->set_addresses($row);
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array( $messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($row['username']), 'USERNAME' => htmlspecialchars_decode($row['username']),

View file

@ -66,7 +66,7 @@ class phpbb_hook_finder
{ {
while (($file = readdir($dh)) !== false) while (($file = readdir($dh)) !== false)
{ {
if (strpos($file, 'hook_') === 0 && substr($file, -(strlen($this->php_ext) + 1)) === '.' . $this->php_ext) if (strpos($file, 'hook_') === 0 && substr($file, -strlen('.' . $this->php_ext)) === '.' . $this->php_ext)
{ {
$hook_files[] = substr($file, 0, -(strlen($this->php_ext) + 1)); $hook_files[] = substr($file, 0, -(strlen($this->php_ext) + 1));
} }

View file

@ -116,6 +116,17 @@ class phpbb_lock_db
return $this->locked; return $this->locked;
} }
/**
* Does this process own the lock?
*
* @return bool true if lock is owned
* false otherwise
*/
public function owns_lock()
{
return (bool) $this->locked;
}
/** /**
* Releases the lock. * Releases the lock.
* *

View file

@ -110,6 +110,17 @@ class phpbb_lock_flock
return (bool) $this->lock_fp; return (bool) $this->lock_fp;
} }
/**
* Does this process own the lock?
*
* @return bool true if lock is owned
* false otherwise
*/
public function owns_lock()
{
return (bool) $this->lock_fp;
}
/** /**
* Releases the lock. * Releases the lock.
* *

View file

@ -256,6 +256,7 @@ class phpbb_notification_manager
SET notification_read = 1 SET notification_read = 1
WHERE notification_time <= " . (int) $time . WHERE notification_time <= " . (int) $time .
(($item_type !== false) ? ' AND ' . (is_array($item_type) ? $this->db->sql_in_set('item_type', $item_type) : " item_type = '" . $this->db->sql_escape($item_type) . "'") : '') . (($item_type !== false) ? ' AND ' . (is_array($item_type) ? $this->db->sql_in_set('item_type', $item_type) : " item_type = '" . $this->db->sql_escape($item_type) . "'") : '') .
(($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') .
(($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : ''); (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : '');
$this->db->sql_query($sql); $this->db->sql_query($sql);
} }
@ -389,7 +390,6 @@ class phpbb_notification_manager
$user_ids = array(); $user_ids = array();
$notification_objects = $notification_methods = array(); $notification_objects = $notification_methods = array();
$new_rows = array();
// Never send notifications to the anonymous user! // Never send notifications to the anonymous user!
unset($notify_users[ANONYMOUS]); unset($notify_users[ANONYMOUS]);
@ -419,6 +419,8 @@ class phpbb_notification_manager
$pre_create_data = $notification->pre_create_insert_array($data, $notify_users); $pre_create_data = $notification->pre_create_insert_array($data, $notify_users);
unset($notification); unset($notification);
$insert_buffer = new phpbb_db_sql_insert_buffer($this->db, $this->notifications_table);
// Go through each user so we can insert a row in the DB and then notify them by their desired means // Go through each user so we can insert a row in the DB and then notify them by their desired means
foreach ($notify_users as $user => $methods) foreach ($notify_users as $user => $methods)
{ {
@ -426,8 +428,8 @@ class phpbb_notification_manager
$notification->user_id = (int) $user; $notification->user_id = (int) $user;
// Store the creation array in our new rows that will be inserted later // Insert notification row using buffer.
$new_rows[] = $notification->create_insert_array($data, $pre_create_data); $insert_buffer->insert($notification->create_insert_array($data, $pre_create_data));
// Users are needed to send notifications // Users are needed to send notifications
$user_ids = array_merge($user_ids, $notification->users_to_query()); $user_ids = array_merge($user_ids, $notification->users_to_query());
@ -447,8 +449,7 @@ class phpbb_notification_manager
} }
} }
// insert into the db $insert_buffer->flush();
$this->db->sql_multi_insert($this->notifications_table, $new_rows);
// We need to load all of the users to send notifications // We need to load all of the users to send notifications
$this->user_loader->load_users($user_ids); $this->user_loader->load_users($user_ids);

View file

@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
* *
* @package notifications * @package notifications
*/ */
class phpbb_notification_method_email extends phpbb_notification_method_base class phpbb_notification_method_email extends phpbb_notification_method_messenger_base
{ {
/** /**
* Get notification method name * Get notification method name
@ -33,27 +33,13 @@ class phpbb_notification_method_email extends phpbb_notification_method_base
return 'email'; return 'email';
} }
/**
* Notify method (since jabber gets sent through the same messenger, we let the jabber class inherit from this to reduce code duplication)
*
* @var mixed
*/
protected $notify_method = NOTIFY_EMAIL;
/**
* Base directory to prepend to the email template name
*
* @var string
*/
protected $email_template_base_dir = '';
/** /**
* Is this method available for the user? * Is this method available for the user?
* This is checked on the notifications options * This is checked on the notifications options
*/ */
public function is_available() public function is_available()
{ {
return (bool) $this->config['email_enable']; return $this->config['email_enable'] && $this->user->data['user_email'];
} }
/** /**
@ -61,68 +47,6 @@ class phpbb_notification_method_email extends phpbb_notification_method_base
*/ */
public function notify() public function notify()
{ {
if (!sizeof($this->queue)) return $this->notify_using_messenger(NOTIFY_EMAIL);
{
return;
}
// Load all users we want to notify (we need their email address)
$user_ids = $users = array();
foreach ($this->queue as $notification)
{
$user_ids[] = $notification->user_id;
}
// We do not send emails to banned users
if (!function_exists('phpbb_get_banned_user_ids'))
{
include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$banned_users = phpbb_get_banned_user_ids($user_ids);
// Load all the users we need
$this->user_loader->load_users($user_ids);
// Load the messenger
if (!class_exists('messenger'))
{
include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
}
$messenger = new messenger();
$board_url = generate_board_url();
// Time to go through the queue and send emails
foreach ($this->queue as $notification)
{
if ($notification->get_email_template() === false)
{
continue;
}
$user = $this->user_loader->get_user($notification->user_id);
if ($user['user_type'] == USER_IGNORE || in_array($notification->user_id, $banned_users))
{
continue;
}
$messenger->template($this->email_template_base_dir . $notification->get_email_template(), $user['user_lang']);
$messenger->to($user['user_email'], $user['username']);
$messenger->assign_vars(array_merge(array(
'USERNAME' => $user['username'],
'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications',
), $notification->get_email_template_variables()));
$messenger->send($this->notify_method);
}
// Save the queue in the messenger class (has to be called or these emails could be lost?)
$messenger->save_queue();
// We're done, empty the queue
$this->empty_queue();
} }
} }

View file

@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
* *
* @package notifications * @package notifications
*/ */
class phpbb_notification_method_jabber extends phpbb_notification_method_email class phpbb_notification_method_jabber extends phpbb_notification_method_messenger_base
{ {
/** /**
* Get notification method name * Get notification method name
@ -33,20 +33,6 @@ class phpbb_notification_method_jabber extends phpbb_notification_method_email
return 'jabber'; return 'jabber';
} }
/**
* Notify method (since jabber gets sent through the same messenger, we let the jabber class inherit from this to reduce code duplication)
*
* @var mixed
*/
protected $notify_method = NOTIFY_IM;
/**
* Base directory to prepend to the email template name
*
* @var string
*/
protected $email_template_base_dir = 'short/';
/** /**
* Is this method available for the user? * Is this method available for the user?
* This is checked on the notifications options * This is checked on the notifications options
@ -62,7 +48,13 @@ class phpbb_notification_method_jabber extends phpbb_notification_method_email
*/ */
public function global_available() public function global_available()
{ {
return ($this->config['jab_enable'] && @extension_loaded('xml')); return !(
empty($this->config['jab_enable']) ||
empty($this->config['jab_host']) ||
empty($this->config['jab_username']) ||
empty($this->config['jab_password']) ||
!@extension_loaded('xml')
);
} }
public function notify() public function notify()
@ -72,6 +64,6 @@ class phpbb_notification_method_jabber extends phpbb_notification_method_email
return; return;
} }
return parent::notify(); return $this->notify_using_messenger(NOTIFY_IM, 'short/');
} }
} }

View file

@ -0,0 +1,100 @@
<?php
/**
*
* @package notifications
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Abstract notification method handling email and jabber notifications
* using the phpBB messenger.
*
* @package notifications
*/
abstract class phpbb_notification_method_messenger_base extends phpbb_notification_method_base
{
/**
* Notify using phpBB messenger
*
* @param int $notify_method Notify method for messenger (e.g. NOTIFY_IM)
* @param string $template_dir_prefix Base directory to prepend to the email template name
*
* @return null
*/
protected function notify_using_messenger($notify_method, $template_dir_prefix = '')
{
if (empty($this->queue))
{
return;
}
// Load all users we want to notify (we need their email address)
$user_ids = $users = array();
foreach ($this->queue as $notification)
{
$user_ids[] = $notification->user_id;
}
// We do not send emails to banned users
if (!function_exists('phpbb_get_banned_user_ids'))
{
include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$banned_users = phpbb_get_banned_user_ids($user_ids);
// Load all the users we need
$this->user_loader->load_users($user_ids);
// Load the messenger
if (!class_exists('messenger'))
{
include($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
}
$messenger = new messenger();
$board_url = generate_board_url();
// Time to go through the queue and send emails
foreach ($this->queue as $notification)
{
if ($notification->get_email_template() === false)
{
continue;
}
$user = $this->user_loader->get_user($notification->user_id);
if ($user['user_type'] == USER_IGNORE || in_array($notification->user_id, $banned_users))
{
continue;
}
$messenger->template($template_dir_prefix . $notification->get_email_template(), $user['user_lang']);
$messenger->set_addresses($user);
$messenger->assign_vars(array_merge(array(
'USERNAME' => $user['username'],
'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications',
), $notification->get_email_template_variables()));
$messenger->send($notify_method);
}
// Save the queue in the messenger class (has to be called or these emails could be lost?)
$messenger->save_queue();
// We're done, empty the queue
$this->empty_queue();
}
}

View file

@ -89,6 +89,7 @@ class phpbb_notification_type_bookmark extends phpbb_notification_type_post
{ {
return array(); return array();
} }
sort($users);
$auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']); $auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);

View file

@ -106,11 +106,26 @@ class phpbb_notification_type_post extends phpbb_notification_type_base
} }
$this->db->sql_freeresult($result); $this->db->sql_freeresult($result);
$sql = 'SELECT user_id
FROM ' . FORUMS_WATCH_TABLE . '
WHERE forum_id = ' . (int) $post['forum_id'] . '
AND notify_status = ' . NOTIFY_YES . '
AND user_id <> ' . (int) $post['poster_id'];
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$users[] = $row['user_id'];
}
$this->db->sql_freeresult($result);
if (empty($users)) if (empty($users))
{ {
return array(); return array();
} }
$users = array_unique($users);
sort($users);
$auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']); $auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);
if (empty($auth_read)) if (empty($auth_read))

View file

@ -82,7 +82,7 @@ class phpbb_notification_type_post_in_queue extends phpbb_notification_type_post
'ignore_users' => array(), 'ignore_users' => array(),
), $options); ), $options);
// 0 is for global // 0 is for global moderator permissions
$auth_approve = $this->auth->acl_get_list(false, $this->permission, array($post['forum_id'], 0)); $auth_approve = $this->auth->acl_get_list(false, $this->permission, array($post['forum_id'], 0));
if (empty($auth_approve)) if (empty($auth_approve))
@ -101,8 +101,15 @@ class phpbb_notification_type_post_in_queue extends phpbb_notification_type_post
{ {
$has_permission = array_unique(array_merge($has_permission, $auth_approve[0][$this->permission])); $has_permission = array_unique(array_merge($has_permission, $auth_approve[0][$this->permission]));
} }
sort($has_permission);
return $this->check_user_notification_options($has_permission, array_merge($options, array( $auth_read = $this->auth->acl_get_list($has_permission, 'f_read', $post['forum_id']);
if (empty($auth_read))
{
return array();
}
return $this->check_user_notification_options($auth_read[$post['forum_id']]['f_read'], array_merge($options, array(
'item_type' => self::$notification_option['id'], 'item_type' => self::$notification_option['id'],
))); )));
} }

View file

@ -108,6 +108,7 @@ class phpbb_notification_type_quote extends phpbb_notification_type_post
{ {
return array(); return array();
} }
sort($users);
$auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']); $auth_read = $this->auth->acl_get_list($users, 'f_read', $post['forum_id']);

View file

@ -82,7 +82,7 @@ class phpbb_notification_type_topic_in_queue extends phpbb_notification_type_top
'ignore_users' => array(), 'ignore_users' => array(),
), $options); ), $options);
// 0 is for global // 0 is for global moderator permissions
$auth_approve = $this->auth->acl_get_list(false, 'm_approve', array($topic['forum_id'], 0)); $auth_approve = $this->auth->acl_get_list(false, 'm_approve', array($topic['forum_id'], 0));
if (empty($auth_approve)) if (empty($auth_approve))
@ -101,8 +101,15 @@ class phpbb_notification_type_topic_in_queue extends phpbb_notification_type_top
{ {
$has_permission = array_unique(array_merge($has_permission, $auth_approve[0][$this->permission])); $has_permission = array_unique(array_merge($has_permission, $auth_approve[0][$this->permission]));
} }
sort($has_permission);
return $this->check_user_notification_options($has_permission, array_merge($options, array( $auth_read = $this->auth->acl_get_list($has_permission, 'f_read', $topic['forum_id']);
if (empty($auth_read))
{
return array();
}
return $this->check_user_notification_options($auth_read[$topic['forum_id']]['f_read'], array_merge($options, array(
'item_type' => self::$notification_option['id'], 'item_type' => self::$notification_option['id'],
))); )));
} }

View file

@ -214,7 +214,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
{ {
if ($terms == 'all') if ($terms == 'all')
{ {
$match = array('#\sand\s#iu', '#\sor\s#iu', '#\snot\s#iu', '#\+#', '#-#', '#\|#'); $match = array('#\sand\s#iu', '#\sor\s#iu', '#\snot\s#iu', '#(^|\s)\+#', '#(^|\s)-#', '#(^|\s)\|#');
$replace = array(' +', ' |', ' -', ' +', ' -', ' |'); $replace = array(' +', ' |', ' -', ' +', ' -', ' |');
$keywords = preg_replace($match, $replace, $keywords); $keywords = preg_replace($match, $replace, $keywords);

View file

@ -40,17 +40,22 @@ class phpbb_style_extension_path_provider extends phpbb_extension_provider imple
*/ */
protected $base_path_provider; protected $base_path_provider;
/** @var string */
protected $phpbb_root_path;
/** /**
* Constructor stores extension manager * Constructor stores extension manager
* *
* @param phpbb_extension_manager $extension_manager phpBB extension manager * @param phpbb_extension_manager $extension_manager phpBB extension manager
* @param phpbb_style_path_provider $base_path_provider A simple path provider * @param phpbb_style_path_provider $base_path_provider A simple path provider
* to provide paths to be located in extensions * to provide paths to be located in extensions
* @param string $phpbb_root_path phpBB root path
*/ */
public function __construct(phpbb_extension_manager $extension_manager, phpbb_style_path_provider $base_path_provider) public function __construct(phpbb_extension_manager $extension_manager, phpbb_style_path_provider $base_path_provider, $phpbb_root_path)
{ {
parent::__construct($extension_manager); parent::__construct($extension_manager);
$this->base_path_provider = $base_path_provider; $this->base_path_provider = $base_path_provider;
$this->phpbb_root_path = $phpbb_root_path;
} }
/** /**
@ -91,10 +96,23 @@ class phpbb_style_extension_path_provider extends phpbb_extension_provider imple
$directories['style'][] = $path; $directories['style'][] = $path;
if ($path && !phpbb_is_absolute($path)) if ($path && !phpbb_is_absolute($path))
{ {
// Remove phpBB root path from the style path,
// so the finder is able to find extension styles,
// when the root path is not ./
if (strpos($path, $this->phpbb_root_path) === 0)
{
$path = substr($path, strlen($this->phpbb_root_path));
}
$result = $finder->directory('/' . $this->ext_dir_prefix . $path) $result = $finder->directory('/' . $this->ext_dir_prefix . $path)
->get_directories(true, false, true); ->get_directories(true, false, true);
foreach ($result as $ext => $ext_path) foreach ($result as $ext => $ext_path)
{ {
// Make sure $ext_path has no ending slash
if (substr($ext_path, -1) === '/')
{
$ext_path = substr($ext_path, 0, -1);
}
$directories[$ext][] = $ext_path; $directories[$ext][] = $ext_path;
} }
} }

View file

@ -224,28 +224,34 @@ class phpbb_template_filter extends php_user_filter
} }
/* /*
Preserve whitespace.
PHP removes a newline after the closing tag (if it's there). This is by design. Preserve whitespace.
PHP removes a newline after the closing tag (if it's there).
This is by design:
http://www.php.net/manual/en/language.basic-syntax.phpmode.php
http://www.php.net/manual/en/language.basic-syntax.instruction-separation.php
Consider the following template: Consider the following template:
<!-- IF condition --> <!-- IF condition -->
some content some content
<!-- ENDIF --> <!-- ENDIF -->
If we were to simply preserve all whitespace, we could simply replace all "?>" tags If we were to simply preserve all whitespace, we could simply
with "?>\n". replace all "?>" tags with "?>\n".
Doing that, would add additional newlines to the compiled tempalte in place of the Doing that, would add additional newlines to the compiled
IF and ENDIF statements. These newlines are unwanted (and one is conditional). template in place of the IF and ENDIF statements. These
The IF and ENDIF are usually on their own line for ease of reading. newlines are unwanted (and one is conditional). The IF and
ENDIF are usually on their own line for ease of reading.
This replacement preserves newlines only for statements that aren't the only statement on a line. This replacement preserves newlines only for statements that
It will NOT preserve newlines at the end of statements in the above examle. are not the only statement on a line. It will NOT preserve
It will preserve newlines in situations like: newlines at the end of statements in the above example.
It will preserve newlines in situations like:
<!-- IF condition -->inline content<!-- ENDIF -->
<!-- IF condition -->inline content<!-- ENDIF -->
*/ */

View file

@ -0,0 +1,122 @@
<?php
/**
*
* @package tree
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
interface phpbb_tree_interface
{
/**
* Inserts an item into the database table and into the tree.
*
* @param array $item The item to be added
* @return array Array with item data as set in the database
*/
public function insert(array $additional_data);
/**
* Delete an item from the tree and from the database table
*
* Also deletes the subtree from the tree and from the database table
*
* @param int $item_id The item to be deleted
* @return array Item ids that have been deleted
*/
public function delete($item_id);
/**
* Move an item by a given delta
*
* An item is only moved up/down within the same parent. If the delta is
* larger then the number of children, the item is moved to the top/bottom
* of the list of children within this parent.
*
* @param int $item_id The item to be moved
* @param int $delta Number of steps to move this item, < 0 => down, > 0 => up
* @return bool True if the item was moved
*/
public function move($item_id, $delta);
/**
* Move an item down by 1
*
* @param int $item_id The item to be moved
* @return bool True if the item was moved
*/
public function move_down($item_id);
/**
* Move an item up by 1
*
* @param int $item_id The item to be moved
* @return bool True if the item was moved
*/
public function move_up($item_id);
/**
* Moves all children of one item to another item
*
* If the new parent already has children, the new children are appended
* to the list.
*
* @param int $current_parent_id The current parent item
* @param int $new_parent_id The new parent item
* @return bool True if any items where moved
*/
public function move_children($current_parent_id, $new_parent_id);
/**
* Change parent item
*
* Moves the item to the bottom of the new parent's list of children
*
* @param int $item_id The item to be moved
* @param int $new_parent_id The new parent item
* @return bool True if the parent was set successfully
*/
public function change_parent($item_id, $new_parent_id);
/**
* Get all items that are either ancestors or descendants of the item
*
* @param int $item_id Id of the item to retrieve the ancestors/descendants from
* @param bool $order_asc Order the items ascendingly (most outer ancestor first)
* @param bool $include_item Should the item matching the given item id be included in the list as well
* @return array Array of items (containing all columns from the item table)
* ID => Item data
*/
public function get_path_and_subtree_data($item_id, $order_asc, $include_item);
/**
* Get all of the item's ancestors
*
* @param int $item_id Id of the item to retrieve the ancestors from
* @param bool $order_asc Order the items ascendingly (most outer ancestor first)
* @param bool $include_item Should the item matching the given item id be included in the list as well
* @return array Array of items (containing all columns from the item table)
* ID => Item data
*/
public function get_path_data($item_id, $order_asc, $include_item);
/**
* Get all of the item's descendants
*
* @param int $item_id Id of the item to retrieve the descendants from
* @param bool $order_asc Order the items ascendingly
* @param bool $include_item Should the item matching the given item id be included in the list as well
* @return array Array of items (containing all columns from the item table)
* ID => Item data
*/
public function get_subtree_data($item_id, $order_asc, $include_item);
}

View file

@ -0,0 +1,850 @@
<?php
/**
*
* @package tree
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
abstract class phpbb_tree_nestedset implements phpbb_tree_interface
{
/** @var phpbb_db_driver */
protected $db;
/** @var phpbb_lock_db */
protected $lock;
/** @var string */
protected $table_name;
/**
* Prefix for the language keys returned by exceptions
* @var string
*/
protected $message_prefix = '';
/**
* Column names in the table
* @var string
*/
protected $column_item_id = 'item_id';
protected $column_left_id = 'left_id';
protected $column_right_id = 'right_id';
protected $column_parent_id = 'parent_id';
protected $column_item_parents = 'item_parents';
/**
* Additional SQL restrictions
* Allows to have multiple nested sets in one table
* @var string
*/
protected $sql_where = '';
/**
* List of item properties to be cached in the item_parents column
* @var array
*/
protected $item_basic_data = array('*');
/**
* Construct
*
* @param phpbb_db_driver $db Database connection
* @param phpbb_lock_db $lock Lock class used to lock the table when moving forums around
* @param string $table_name Table name
* @param string $message_prefix Prefix for the messages thrown by exceptions
* @param string $sql_where Additional SQL restrictions for the queries
* @param array $item_basic_data Array with basic item data that is stored in item_parents
* @param array $columns Array with column names to overwrite
*/
public function __construct(phpbb_db_driver $db, phpbb_lock_db $lock, $table_name, $message_prefix = '', $sql_where = '', $item_basic_data = array(), $columns = array())
{
$this->db = $db;
$this->lock = $lock;
$this->table_name = $table_name;
$this->message_prefix = $message_prefix;
$this->sql_where = $sql_where;
$this->item_basic_data = (!empty($item_basic_data)) ? $item_basic_data : array('*');
if (!empty($columns))
{
foreach ($columns as $column => $name)
{
$column_name = 'column_' . $column;
$this->$column_name = $name;
}
}
}
/**
* Returns additional sql where restrictions
*
* @param string $operator SQL operator that needs to be prepended to sql_where,
* if it is not empty.
* @param string $column_prefix Prefix that needs to be prepended to column names
* @return string Returns additional where statements to narrow down the tree,
* prefixed with operator and prepended column_prefix to column names
*/
public function get_sql_where($operator = 'AND', $column_prefix = '')
{
return (!$this->sql_where) ? '' : $operator . ' ' . sprintf($this->sql_where, $column_prefix);
}
/**
* Acquires a lock on the item table
*
* @return bool True if the lock was acquired, false if it has been acquired previously
*
* @throws RuntimeException If the lock could not be acquired
*/
protected function acquire_lock()
{
if ($this->lock->owns_lock())
{
return false;
}
if (!$this->lock->acquire())
{
throw new RuntimeException($this->message_prefix . 'LOCK_FAILED_ACQUIRE');
}
return true;
}
/**
* @inheritdoc
*/
public function insert(array $additional_data)
{
$item_data = $this->reset_nestedset_values($additional_data);
$sql = 'INSERT INTO ' . $this->table_name . ' ' . $this->db->sql_build_array('INSERT', $item_data);
$this->db->sql_query($sql);
$item_data[$this->column_item_id] = (int) $this->db->sql_nextid();
return array_merge($item_data, $this->add_item_to_nestedset($item_data[$this->column_item_id]));
}
/**
* Add an item which already has a database row at the end of the tree
*
* @param int $item_id The item to be added
* @return array Array with updated data, if the item was added successfully
* Empty array otherwise
*/
protected function add_item_to_nestedset($item_id)
{
$sql = 'SELECT MAX(' . $this->column_right_id . ') AS ' . $this->column_right_id . '
FROM ' . $this->table_name . '
' . $this->get_sql_where('WHERE');
$result = $this->db->sql_query($sql);
$current_max_right_id = (int) $this->db->sql_fetchfield($this->column_right_id);
$this->db->sql_freeresult($result);
$update_item_data = array(
$this->column_parent_id => 0,
$this->column_left_id => $current_max_right_id + 1,
$this->column_right_id => $current_max_right_id + 2,
$this->column_item_parents => '',
);
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->db->sql_build_array('UPDATE', $update_item_data) . '
WHERE ' . $this->column_item_id . ' = ' . (int) $item_id . '
AND ' . $this->column_parent_id . ' = 0
AND ' . $this->column_left_id . ' = 0
AND ' . $this->column_right_id . ' = 0';
$this->db->sql_query($sql);
return ($this->db->sql_affectedrows() == 1) ? $update_item_data : array();
}
/**
* Remove an item from the tree without deleting it from the database
*
* Also removes all subitems from the tree without deleting them from the database either
*
* @param int $item_id The item to be deleted
* @return array Item ids that have been removed
*/
protected function remove_item_from_nestedset($item_id)
{
$item_id = (int) $item_id;
if (!$item_id)
{
throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM');
}
$items = $this->get_subtree_data($item_id);
$item_ids = array_keys($items);
if (empty($items) || !isset($items[$item_id]))
{
throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM');
}
$this->remove_subset($item_ids, $items[$item_id]);
return $item_ids;
}
/**
* @inheritdoc
*/
public function delete($item_id)
{
$removed_items = $this->remove_item_from_nestedset($item_id);
$sql = 'DELETE FROM ' . $this->table_name . '
WHERE ' . $this->db->sql_in_set($this->column_item_id, $removed_items) . '
' . $this->get_sql_where('AND');
$this->db->sql_query($sql);
return $removed_items;
}
/**
* @inheritdoc
*/
public function move($item_id, $delta)
{
if ($delta == 0)
{
return false;
}
$this->acquire_lock();
$action = ($delta > 0) ? 'move_up' : 'move_down';
$delta = abs($delta);
// Keep $this->get_sql_where() here, to ensure we are in the right tree.
$sql = 'SELECT *
FROM ' . $this->table_name . '
WHERE ' . $this->column_item_id . ' = ' . (int) $item_id . '
' . $this->get_sql_where();
$result = $this->db->sql_query_limit($sql, $delta);
$item = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if (!$item)
{
$this->lock->release();
throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM');
}
/**
* Fetch all the siblings between the item's current spot
* and where we want to move it to. If there are less than $delta
* siblings between the current spot and the target then the
* item will move as far as possible
*/
$sql = "SELECT {$this->column_item_id}, {$this->column_parent_id}, {$this->column_left_id}, {$this->column_right_id}, {$this->column_item_parents}
FROM " . $this->table_name . '
WHERE ' . $this->column_parent_id . ' = ' . (int) $item[$this->column_parent_id] . '
' . $this->get_sql_where() . '
AND ';
if ($action == 'move_up')
{
$sql .= $this->column_right_id . ' < ' . (int) $item[$this->column_right_id] . ' ORDER BY ' . $this->column_right_id . ' DESC';
}
else
{
$sql .= $this->column_left_id . ' > ' . (int) $item[$this->column_left_id] . ' ORDER BY ' . $this->column_left_id . ' ASC';
}
$result = $this->db->sql_query_limit($sql, $delta);
$target = false;
while ($row = $this->db->sql_fetchrow($result))
{
$target = $row;
}
$this->db->sql_freeresult($result);
if (!$target)
{
$this->lock->release();
// The item is already on top or bottom
return false;
}
/**
* $left_id and $right_id define the scope of the items that are affected by the move.
* $diff_up and $diff_down are the values to substract or add to each item's left_id
* and right_id in order to move them up or down.
* $move_up_left and $move_up_right define the scope of the items that are moving
* up. Other items in the scope of ($left_id, $right_id) are considered to move down.
*/
if ($action == 'move_up')
{
$left_id = (int) $target[$this->column_left_id];
$right_id = (int) $item[$this->column_right_id];
$diff_up = (int) $item[$this->column_left_id] - (int) $target[$this->column_left_id];
$diff_down = (int) $item[$this->column_right_id] + 1 - (int) $item[$this->column_left_id];
$move_up_left = (int) $item[$this->column_left_id];
$move_up_right = (int) $item[$this->column_right_id];
}
else
{
$left_id = (int) $item[$this->column_left_id];
$right_id = (int) $target[$this->column_right_id];
$diff_up = (int) $item[$this->column_right_id] + 1 - (int) $item[$this->column_left_id];
$diff_down = (int) $target[$this->column_right_id] - (int) $item[$this->column_right_id];
$move_up_left = (int) $item[$this->column_right_id] + 1;
$move_up_right = (int) $target[$this->column_right_id];
}
// Now do the dirty job
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->column_left_id . ' = ' . $this->column_left_id . ' + CASE
WHEN ' . $this->column_left_id . " BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
ELSE {$diff_down}
END,
" . $this->column_right_id . ' = ' . $this->column_right_id . ' + CASE
WHEN ' . $this->column_right_id . " BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
ELSE {$diff_down}
END
WHERE
" . $this->column_left_id . " BETWEEN {$left_id} AND {$right_id}
AND " . $this->column_right_id . " BETWEEN {$left_id} AND {$right_id}
" . $this->get_sql_where();
$this->db->sql_query($sql);
$this->lock->release();
return true;
}
/**
* @inheritdoc
*/
public function move_down($item_id)
{
return $this->move($item_id, -1);
}
/**
* @inheritdoc
*/
public function move_up($item_id)
{
return $this->move($item_id, 1);
}
/**
* @inheritdoc
*/
public function move_children($current_parent_id, $new_parent_id)
{
$current_parent_id = (int) $current_parent_id;
$new_parent_id = (int) $new_parent_id;
if ($current_parent_id == $new_parent_id)
{
return false;
}
if (!$current_parent_id)
{
throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM');
}
$this->acquire_lock();
$item_data = $this->get_subtree_data($current_parent_id);
if (!isset($item_data[$current_parent_id]))
{
$this->lock->release();
throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM');
}
$current_parent = $item_data[$current_parent_id];
unset($item_data[$current_parent_id]);
$move_items = array_keys($item_data);
if (($current_parent[$this->column_right_id] - $current_parent[$this->column_left_id]) <= 1)
{
$this->lock->release();
return false;
}
if (in_array($new_parent_id, $move_items))
{
$this->lock->release();
throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT');
}
$diff = sizeof($move_items) * 2;
$sql_exclude_moved_items = $this->db->sql_in_set($this->column_item_id, $move_items, true);
$this->db->sql_transaction('begin');
$this->remove_subset($move_items, $current_parent, false, true);
if ($new_parent_id)
{
// Retrieve new-parent again, it may have been changed...
$sql = 'SELECT *
FROM ' . $this->table_name . '
WHERE ' . $this->column_item_id . ' = ' . $new_parent_id;
$result = $this->db->sql_query($sql);
$new_parent = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if (!$new_parent)
{
$this->db->sql_transaction('rollback');
$this->lock->release();
throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT');
}
$new_right_id = $this->prepare_adding_subset($move_items, $new_parent, true);
if ($new_right_id > $current_parent[$this->column_right_id])
{
$diff = ' + ' . ($new_right_id - $current_parent[$this->column_right_id]);
}
else
{
$diff = ' - ' . abs($new_right_id - $current_parent[$this->column_right_id]);
}
}
else
{
$sql = 'SELECT MAX(' . $this->column_right_id . ') AS ' . $this->column_right_id . '
FROM ' . $this->table_name . '
WHERE ' . $sql_exclude_moved_items . '
' . $this->get_sql_where('AND');
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
$diff = ' + ' . ($row[$this->column_right_id] - $current_parent[$this->column_left_id]);
}
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->column_left_id . ' = ' . $this->column_left_id . $diff . ',
' . $this->column_right_id . ' = ' . $this->column_right_id . $diff . ',
' . $this->column_parent_id . ' = ' . $this->db->sql_case($this->column_parent_id . ' = ' . $current_parent_id, $new_parent_id, $this->column_parent_id) . ',
' . $this->column_item_parents . " = ''
WHERE " . $this->db->sql_in_set($this->column_item_id, $move_items) . '
' . $this->get_sql_where('AND');
$this->db->sql_query($sql);
$this->db->sql_transaction('commit');
$this->lock->release();
return true;
}
/**
* @inheritdoc
*/
public function change_parent($item_id, $new_parent_id)
{
$item_id = (int) $item_id;
$new_parent_id = (int) $new_parent_id;
if ($item_id == $new_parent_id)
{
return false;
}
if (!$item_id)
{
throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM');
}
$this->acquire_lock();
$item_data = $this->get_subtree_data($item_id);
if (!isset($item_data[$item_id]))
{
$this->lock->release();
throw new OutOfBoundsException($this->message_prefix . 'INVALID_ITEM');
}
$item = $item_data[$item_id];
$move_items = array_keys($item_data);
if (in_array($new_parent_id, $move_items))
{
$this->lock->release();
throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT');
}
$diff = sizeof($move_items) * 2;
$sql_exclude_moved_items = $this->db->sql_in_set($this->column_item_id, $move_items, true);
$this->db->sql_transaction('begin');
$this->remove_subset($move_items, $item, false, true);
if ($new_parent_id)
{
// Retrieve new-parent again, it may have been changed...
$sql = 'SELECT *
FROM ' . $this->table_name . '
WHERE ' . $this->column_item_id . ' = ' . $new_parent_id;
$result = $this->db->sql_query($sql);
$new_parent = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if (!$new_parent)
{
$this->db->sql_transaction('rollback');
$this->lock->release();
throw new OutOfBoundsException($this->message_prefix . 'INVALID_PARENT');
}
$new_right_id = $this->prepare_adding_subset($move_items, $new_parent, true);
if ($new_right_id > (int) $item[$this->column_right_id])
{
$diff = ' + ' . ($new_right_id - (int) $item[$this->column_right_id] - 1);
}
else
{
$diff = ' - ' . abs($new_right_id - (int) $item[$this->column_right_id] - 1);
}
}
else
{
$sql = 'SELECT MAX(' . $this->column_right_id . ') AS ' . $this->column_right_id . '
FROM ' . $this->table_name . '
WHERE ' . $sql_exclude_moved_items . '
' . $this->get_sql_where('AND');
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
$diff = ' + ' . ($row[$this->column_right_id] - (int) $item[$this->column_left_id] + 1);
}
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->column_left_id . ' = ' . $this->column_left_id . $diff . ',
' . $this->column_right_id . ' = ' . $this->column_right_id . $diff . ',
' . $this->column_parent_id . ' = ' . $this->db->sql_case($this->column_item_id . ' = ' . $item_id, $new_parent_id, $this->column_parent_id) . ',
' . $this->column_item_parents . " = ''
WHERE " . $this->db->sql_in_set($this->column_item_id, $move_items) . '
' . $this->get_sql_where('AND');
$this->db->sql_query($sql);
$this->db->sql_transaction('commit');
$this->lock->release();
return true;
}
/**
* @inheritdoc
*/
public function get_path_and_subtree_data($item_id, $order_asc = true, $include_item = true)
{
$condition = 'i2.' . $this->column_left_id . ' BETWEEN i1.' . $this->column_left_id . ' AND i1.' . $this->column_right_id . '
OR i1.' . $this->column_left_id . ' BETWEEN i2.' . $this->column_left_id . ' AND i2.' . $this->column_right_id;
return $this->get_set_of_nodes_data($item_id, $condition, $order_asc, $include_item);
}
/**
* @inheritdoc
*/
public function get_path_data($item_id, $order_asc = true, $include_item = true)
{
$condition = 'i1.' . $this->column_left_id . ' BETWEEN i2.' . $this->column_left_id . ' AND i2.' . $this->column_right_id . '';
return $this->get_set_of_nodes_data($item_id, $condition, $order_asc, $include_item);
}
/**
* @inheritdoc
*/
public function get_subtree_data($item_id, $order_asc = true, $include_item = true)
{
$condition = 'i2.' . $this->column_left_id . ' BETWEEN i1.' . $this->column_left_id . ' AND i1.' . $this->column_right_id . '';
return $this->get_set_of_nodes_data($item_id, $condition, $order_asc, $include_item);
}
/**
* Get items that are related to the given item by the condition
*
* @param int $item_id Id of the item to retrieve the node set from
* @param string $condition Query string restricting the item list
* @param bool $order_asc Order the items ascending by their left_id
* @param bool $include_item Should the item matching the given item id be included in the list as well
* @return array Array of items (containing all columns from the item table)
* ID => Item data
*/
protected function get_set_of_nodes_data($item_id, $condition, $order_asc = true, $include_item = true)
{
$rows = array();
$sql = 'SELECT i2.*
FROM ' . $this->table_name . ' i1
LEFT JOIN ' . $this->table_name . " i2
ON (($condition) " . $this->get_sql_where('AND', 'i2.') . ')
WHERE i1.' . $this->column_item_id . ' = ' . (int) $item_id . '
' . $this->get_sql_where('AND', 'i1.') . '
ORDER BY i2.' . $this->column_left_id . ' ' . ($order_asc ? 'ASC' : 'DESC');
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
if (!$include_item && $item_id == $row[$this->column_item_id])
{
continue;
}
$rows[(int) $row[$this->column_item_id]] = $row;
}
$this->db->sql_freeresult($result);
return $rows;
}
/**
* Get basic data of all parent items
*
* Basic data is defined in the $item_basic_data property.
* Data is cached in the item_parents column in the item table
*
* @param array $item The item to get the path from
* @return array Array of items (containing basic columns from the item table)
* ID => Item data
*/
public function get_path_basic_data(array $item)
{
$parents = array();
if ($item[$this->column_parent_id])
{
if (!$item[$this->column_item_parents])
{
$sql = 'SELECT ' . implode(', ', $this->item_basic_data) . '
FROM ' . $this->table_name . '
WHERE ' . $this->column_left_id . ' < ' . (int) $item[$this->column_left_id] . '
AND ' . $this->column_right_id . ' > ' . (int) $item[$this->column_right_id] . '
' . $this->get_sql_where('AND') . '
ORDER BY ' . $this->column_left_id . ' ASC';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$parents[$row[$this->column_item_id]] = $row;
}
$this->db->sql_freeresult($result);
$item_parents = serialize($parents);
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->column_item_parents . " = '" . $this->db->sql_escape($item_parents) . "'
WHERE " . $this->column_parent_id . ' = ' . (int) $item[$this->column_parent_id];
$this->db->sql_query($sql);
}
else
{
$parents = unserialize($item[$this->column_item_parents]);
}
}
return $parents;
}
/**
* Remove a subset from the nested set
*
* @param array $subset_items Subset of items to remove
* @param array $bounding_item Item containing the right bound of the subset
* @param bool $set_subset_zero Should the parent, left and right id of the items be set to 0, or kept unchanged?
* In case of removing an item from the tree, we should the values to 0
* In case of moving an item, we shouldkeep the original values, in order to allow "+ diff" later
* @return null
*/
protected function remove_subset(array $subset_items, array $bounding_item, $set_subset_zero = true)
{
$acquired_new_lock = $this->acquire_lock();
$diff = sizeof($subset_items) * 2;
$sql_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items);
$sql_not_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items, true);
$sql_is_parent = $this->column_left_id . ' <= ' . (int) $bounding_item[$this->column_right_id] . '
AND ' . $this->column_right_id . ' >= ' . (int) $bounding_item[$this->column_right_id];
$sql_is_right = $this->column_left_id . ' > ' . (int) $bounding_item[$this->column_right_id];
$set_left_id = $this->db->sql_case($sql_is_right, $this->column_left_id . ' - ' . $diff, $this->column_left_id);
$set_right_id = $this->db->sql_case($sql_is_parent . ' OR ' . $sql_is_right, $this->column_right_id . ' - ' . $diff, $this->column_right_id);
if ($set_subset_zero)
{
$set_left_id = $this->db->sql_case($sql_subset_items, 0, $set_left_id);
$set_right_id = $this->db->sql_case($sql_subset_items, 0, $set_right_id);
}
$sql = 'UPDATE ' . $this->table_name . '
SET ' . (($set_subset_zero) ? $this->column_parent_id . ' = ' . $this->db->sql_case($sql_subset_items, 0, $this->column_parent_id) . ',' : '') . '
' . $this->column_left_id . ' = ' . $set_left_id . ',
' . $this->column_right_id . ' = ' . $set_right_id . '
' . ((!$set_subset_zero) ? ' WHERE ' . $sql_not_subset_items . ' ' . $this->get_sql_where('AND') : $this->get_sql_where('WHERE'));
$this->db->sql_query($sql);
if ($acquired_new_lock)
{
$this->lock->release();
}
}
/**
* Prepare adding a subset to the nested set
*
* @param array $subset_items Subset of items to add
* @param array $new_parent Item containing the right bound of the new parent
* @return int New right id of the parent item
*/
protected function prepare_adding_subset(array $subset_items, array $new_parent)
{
$diff = sizeof($subset_items) * 2;
$sql_not_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items, true);
$set_left_id = $this->db->sql_case($this->column_left_id . ' > ' . (int) $new_parent[$this->column_right_id], $this->column_left_id . ' + ' . $diff, $this->column_left_id);
$set_right_id = $this->db->sql_case($this->column_right_id . ' >= ' . (int) $new_parent[$this->column_right_id], $this->column_right_id . ' + ' . $diff, $this->column_right_id);
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->column_left_id . ' = ' . $set_left_id . ',
' . $this->column_right_id . ' = ' . $set_right_id . '
WHERE ' . $sql_not_subset_items . '
' . $this->get_sql_where('AND');
$this->db->sql_query($sql);
return $new_parent[$this->column_right_id] + $diff;
}
/**
* Resets values required for the nested set system
*
* @param array $item Original item data
* @return array Original item data + nested set defaults
*/
protected function reset_nestedset_values(array $item)
{
$item_data = array_merge($item, array(
$this->column_parent_id => 0,
$this->column_left_id => 0,
$this->column_right_id => 0,
$this->column_item_parents => '',
));
unset($item_data[$this->column_item_id]);
return $item_data;
}
/**
* Regenerate left/right ids from parent/child relationship
*
* This method regenerates the left/right ids for the tree based on
* the parent/child relations. This function executes three queries per
* item, so it should only be called, when the set has one of the following
* problems:
* - The set has a duplicated value inside the left/right id chain
* - The set has a missing value inside the left/right id chain
* - The set has items that do not have a left/right id set
*
* When regenerating the items, the items are sorted by parent id and their
* current left id, so the current child/parent relationships are kept
* and running the function on a working set will not change the order.
*
* @param int $new_id First left_id to be used (should start with 1)
* @param int $parent_id parent_id of the current set (default = 0)
* @param bool $reset_ids Should we reset all left_id/right_id on the first call?
* @return int $new_id The next left_id/right_id that should be used
*/
public function regenerate_left_right_ids($new_id, $parent_id = 0, $reset_ids = false)
{
if ($acquired_new_lock = $this->acquire_lock())
{
$this->db->sql_transaction('begin');
if (!$reset_ids)
{
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->column_item_parents . " = ''
" . $this->get_sql_where('WHERE');
$this->db->sql_query($sql);
}
}
if ($reset_ids)
{
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->db->sql_build_array('UPDATE', array(
$this->column_left_id => 0,
$this->column_right_id => 0,
$this->column_item_parents => '',
)) . '
' . $this->get_sql_where('WHERE');
$this->db->sql_query($sql);
}
$sql = 'SELECT *
FROM ' . $this->table_name . '
WHERE ' . $this->column_parent_id . ' = ' . (int) $parent_id . '
' . $this->get_sql_where('AND') . '
ORDER BY ' . $this->column_left_id . ', ' . $this->column_item_id . ' ASC';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
// First we update the left_id for this module
if ($row[$this->column_left_id] != $new_id)
{
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->db->sql_build_array('UPDATE', array($this->column_left_id => $new_id)) . '
WHERE ' . $this->column_item_id . ' = ' . (int) $row[$this->column_item_id];
$this->db->sql_query($sql);
}
$new_id++;
// Then we go through any children and update their left/right id's
$new_id = $this->regenerate_left_right_ids($new_id, $row[$this->column_item_id]);
// Then we come back and update the right_id for this module
if ($row[$this->column_right_id] != $new_id)
{
$sql = 'UPDATE ' . $this->table_name . '
SET ' . $this->db->sql_build_array('UPDATE', array($this->column_right_id => $new_id)) . '
WHERE ' . $this->column_item_id . ' = ' . (int) $row[$this->column_item_id];
$this->db->sql_query($sql);
}
$new_id++;
}
$this->db->sql_freeresult($result);
if ($acquired_new_lock)
{
$this->db->sql_transaction('commit');
$this->lock->release();
}
return $new_id;
}
}

View file

@ -0,0 +1,46 @@
<?php
/**
*
* @package tree
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_tree_nestedset_forum extends phpbb_tree_nestedset
{
/**
* Construct
*
* @param phpbb_db_driver $db Database connection
* @param phpbb_lock_db $lock Lock class used to lock the table when moving forums around
* @param string $table_name Table name
*/
public function __construct(phpbb_db_driver $db, phpbb_lock_db $lock, $table_name)
{
parent::__construct(
$db,
$lock,
$table_name,
'FORUM_NESTEDSET_',
'',
array(
'forum_id',
'forum_name',
'forum_type',
),
array(
'item_id' => 'forum_id',
'item_parents' => 'forum_parents',
)
);
}
}

View file

@ -114,7 +114,7 @@ class ucp_activate
$messenger->template('admin_welcome_activated', $user_row['user_lang']); $messenger->template('admin_welcome_activated', $user_row['user_lang']);
$messenger->to($user_row['user_email'], $user_row['username']); $messenger->set_addresses($user_row);
$messenger->anti_abuse_headers($config, $user); $messenger->anti_abuse_headers($config, $user);

View file

@ -212,8 +212,7 @@ class ucp_groups
{ {
$messenger->template('group_request', $row['user_lang']); $messenger->template('group_request', $row['user_lang']);
$messenger->to($row['user_email'], $row['username']); $messenger->set_addresses($row);
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array( $messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($row['username']), 'USERNAME' => htmlspecialchars_decode($row['username']),

View file

@ -265,19 +265,16 @@ function compose_pm($id, $mode, $action, $user_folders = array())
// Passworded forum? // Passworded forum?
if ($post['forum_id']) if ($post['forum_id'])
{ {
$sql = 'SELECT forum_password $sql = 'SELECT forum_id, forum_name, forum_password
FROM ' . FORUMS_TABLE . ' FROM ' . FORUMS_TABLE . '
WHERE forum_id = ' . (int) $post['forum_id']; WHERE forum_id = ' . (int) $post['forum_id'];
$result = $db->sql_query($sql); $result = $db->sql_query($sql);
$forum_password = (string) $db->sql_fetchfield('forum_password'); $forum_data = $db->sql_fetchrow($result);
$db->sql_freeresult($result); $db->sql_freeresult($result);
if ($forum_password) if (!empty($forum_data['forum_password']))
{ {
login_forum_box(array( login_forum_box($forum_data);
'forum_id' => $post['forum_id'],
'forum_password' => $forum_password,
));
} }
} }
} }

View file

@ -94,8 +94,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
// Editing information // Editing information
if ($message_row['message_edit_count'] && $config['display_last_edited']) if ($message_row['message_edit_count'] && $config['display_last_edited'])
{ {
$l_edit_time_total = ($message_row['message_edit_count'] == 1) ? $user->lang['EDITED_TIME_TOTAL'] : $user->lang['EDITED_TIMES_TOTAL']; $l_edited_by = '<br /><br />' . $user->lang('EDITED_TIMES_TOTAL', (int) $message_row['message_edit_count'], (!$message_row['message_edit_user']) ? $message_row['username'] : $message_row['message_edit_user'], $user->format_date($message_row['message_edit_time'], false, true));
$l_edited_by = '<br /><br />' . sprintf($l_edit_time_total, (!$message_row['message_edit_user']) ? $message_row['username'] : $message_row['message_edit_user'], $user->format_date($message_row['message_edit_time'], false, true), $message_row['message_edit_count']);
} }
else else
{ {

View file

@ -175,8 +175,7 @@ class ucp_profile
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
$messenger->template('admin_activate', $row['user_lang']); $messenger->template('admin_activate', $row['user_lang']);
$messenger->to($row['user_email'], $row['username']); $messenger->set_addresses($row);
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array( $messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($data['username']), 'USERNAME' => htmlspecialchars_decode($data['username']),

View file

@ -384,8 +384,7 @@ class ucp_register
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
$messenger->template('admin_activate', $row['user_lang']); $messenger->template('admin_activate', $row['user_lang']);
$messenger->to($row['user_email'], $row['username']); $messenger->set_addresses($row);
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array( $messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($data['username']), 'USERNAME' => htmlspecialchars_decode($data['username']),

View file

@ -29,6 +29,11 @@ class ucp_remind
global $config, $phpbb_root_path, $phpEx; global $config, $phpbb_root_path, $phpEx;
global $db, $user, $auth, $template; global $db, $user, $auth, $template;
if (!$config['allow_password_reset'])
{
trigger_error($user->lang('UCP_PASSWORD_RESET_DISABLED', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'));
}
$username = request_var('username', '', true); $username = request_var('username', '', true);
$email = strtolower(request_var('email', '')); $email = strtolower(request_var('email', ''));
$submit = (isset($_POST['submit'])) ? true : false; $submit = (isset($_POST['submit'])) ? true : false;
@ -94,8 +99,7 @@ class ucp_remind
$messenger->template('user_activate_passwd', $user_row['user_lang']); $messenger->template('user_activate_passwd', $user_row['user_lang']);
$messenger->to($user_row['user_email'], $user_row['username']); $messenger->set_addresses($user_row);
$messenger->im($user_row['user_jabber'], $user_row['username']);
$messenger->assign_vars(array( $messenger->assign_vars(array(
'USERNAME' => htmlspecialchars_decode($user_row['username']), 'USERNAME' => htmlspecialchars_decode($user_row['username']),

View file

@ -91,7 +91,7 @@ class ucp_resend
if ($config['require_activation'] == USER_ACTIVATION_SELF || $coppa) if ($config['require_activation'] == USER_ACTIVATION_SELF || $coppa)
{ {
$messenger->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); $messenger->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']);
$messenger->to($user_row['user_email'], $user_row['username']); $messenger->set_addresses($user_row);
$messenger->anti_abuse_headers($config, $user); $messenger->anti_abuse_headers($config, $user);
@ -126,8 +126,7 @@ class ucp_resend
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
$messenger->template('admin_activate', $row['user_lang']); $messenger->template('admin_activate', $row['user_lang']);
$messenger->to($row['user_email'], $row['username']); $messenger->set_addresses($row);
$messenger->im($row['user_jabber'], $row['username']);
$messenger->anti_abuse_headers($config, $user); $messenger->anti_abuse_headers($config, $user);

View file

@ -215,7 +215,7 @@ class phpbb_user extends phpbb_session
if (!$this->style) if (!$this->style)
{ {
trigger_error('Could not get style data', E_USER_ERROR); trigger_error('NO_STYLE_DATA', E_USER_ERROR);
} }
// Now parse the cfg file and cache it // Now parse the cfg file and cache it

View file

@ -70,8 +70,8 @@ class phpbb_user_loader
{ {
$user_ids[] = ANONYMOUS; $user_ids[] = ANONYMOUS;
// Load the users // Make user_ids unique and convert to integer.
$user_ids = array_unique($user_ids); $user_ids = array_map('intval', array_unique($user_ids));
// Do not load users we already have in $this->users // Do not load users we already have in $this->users
$user_ids = array_diff($user_ids, array_keys($this->users)); $user_ids = array_diff($user_ids, array_keys($this->users));

View file

@ -41,10 +41,12 @@ if (!function_exists('phpbb_require_updated'))
} }
} }
function phpbb_end_update($cache) function phpbb_end_update($cache, $config)
{ {
$cache->purge(); $cache->purge();
$config->increment('assets_version', 1);
?> ?>
</p> </p>
</div> </div>
@ -93,7 +95,7 @@ require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
// Setup class loader first // Setup class loader first
$phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); $phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", $phpEx);
$phpbb_class_loader->register(); $phpbb_class_loader->register();
// Set up container (must be done here because extensions table may not exist) // Set up container (must be done here because extensions table may not exist)
@ -232,7 +234,7 @@ while (!$migrator->finished())
{ {
echo $e->getLocalisedMessage($user); echo $e->getLocalisedMessage($user);
phpbb_end_update($cache); phpbb_end_update($cache, $config);
} }
$state = array_merge(array( $state = array_merge(array(
@ -265,7 +267,7 @@ while (!$migrator->finished())
echo $user->lang['DATABASE_UPDATE_NOT_COMPLETED'] . '<br />'; echo $user->lang['DATABASE_UPDATE_NOT_COMPLETED'] . '<br />';
echo '<a href="' . append_sid($phpbb_root_path . 'test.' . $phpEx) . '">' . $user->lang['DATABASE_UPDATE_CONTINUE'] . '</a>'; echo '<a href="' . append_sid($phpbb_root_path . 'test.' . $phpEx) . '">' . $user->lang['DATABASE_UPDATE_CONTINUE'] . '</a>';
phpbb_end_update($cache); phpbb_end_update($cache, $config);
} }
} }
@ -276,4 +278,4 @@ if ($orig_version != $config['version'])
echo $user->lang['DATABASE_UPDATE_COMPLETE']; echo $user->lang['DATABASE_UPDATE_COMPLETE'];
phpbb_end_update($cache); phpbb_end_update($cache, $config);

View file

@ -90,9 +90,9 @@ include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
require($phpbb_root_path . 'includes/functions_install.' . $phpEx); require($phpbb_root_path . 'includes/functions_install.' . $phpEx);
// Setup class loader first // Setup class loader first
$phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); $phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", $phpEx);
$phpbb_class_loader->register(); $phpbb_class_loader->register();
$phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", ".$phpEx"); $phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", $phpEx);
$phpbb_class_loader_ext->register(); $phpbb_class_loader_ext->register();
// Set up container // Set up container

View file

@ -72,7 +72,13 @@ class install_update extends module
function main($mode, $sub) function main($mode, $sub)
{ {
global $phpbb_style, $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language; global $phpbb_style, $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language;
global $request, $phpbb_admin_path, $phpbb_adm_relative_path; global $request, $phpbb_admin_path, $phpbb_adm_relative_path, $phpbb_container;
// Create a normal container now
$phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx);
// Writes into global $cache
$cache = $phpbb_container->get('cache');
$this->tpl_name = 'install_update'; $this->tpl_name = 'install_update';
$this->page_title = 'UPDATE_INSTALLATION'; $this->page_title = 'UPDATE_INSTALLATION';

View file

@ -18,6 +18,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bbcode', '1'
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_birthdays', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_birthdays', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bookmarks', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bookmarks', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_emailreuse', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_emailreuse', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_password_reset', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_forum_notify', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_forum_notify', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_mass_pm', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_mass_pm', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_name_chars', 'USERNAME_CHARS_ANY'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_name_chars', 'USERNAME_CHARS_ANY');
@ -59,6 +60,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email', 'add
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_sig', '{L_CONFIG_BOARD_EMAIL_SIG}'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_sig', '{L_CONFIG_BOARD_EMAIL_SIG}');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_hide_emails', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_hide_emails', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_index_text', '');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_timezone', 'UTC'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_timezone', 'UTC');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('browser_check', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('browser_check', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_interval', '10'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_interval', '10');
@ -173,7 +175,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewtopic
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_lastread', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_lastread', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_track', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_track', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_cdn', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_cdn', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_notifications', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_notifications', '1');
@ -777,9 +779,9 @@ INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogg');
INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogm'); INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogm');
# User Notification Options (for first user) # User Notification Options (for first user)
INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('phpbb_notification_type_post', 0, 2, ''); INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('post', 0, 2, '');
INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('phpbb_notification_type_post', 0, 2, 'phpbb_notification_method_email'); INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('post', 0, 2, 'email');
INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('phpbb_notification_type_topic', 0, 2, ''); INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('topic', 0, 2, '');
INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('phpbb_notification_type_topic', 0, 2, 'phpbb_notification_method_email'); INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('topic', 0, 2, 'email');
# POSTGRES COMMIT # # POSTGRES COMMIT #

View file

@ -37,6 +37,8 @@ if (empty($lang) || !is_array($lang))
// Board Settings // Board Settings
$lang = array_merge($lang, array( $lang = array_merge($lang, array(
'ACP_BOARD_SETTINGS_EXPLAIN' => 'Here you can determine the basic operation of your board, give it a fitting name and description, and among other settings adjust the default values for timezone and language.', 'ACP_BOARD_SETTINGS_EXPLAIN' => 'Here you can determine the basic operation of your board, give it a fitting name and description, and among other settings adjust the default values for timezone and language.',
'BOARD_INDEX_TEXT' => 'Board index text',
'BOARD_INDEX_TEXT_EXPLAIN' => 'This text is displayed as the board index in the boards breadcrumbs. If not specified, it will default to “Board index”.',
'CUSTOM_DATEFORMAT' => 'Custom…', 'CUSTOM_DATEFORMAT' => 'Custom…',
'DEFAULT_DATE_FORMAT' => 'Date format', 'DEFAULT_DATE_FORMAT' => 'Date format',
'DEFAULT_DATE_FORMAT_EXPLAIN' => 'The date format is the same as the PHP <code>date</code> function.', 'DEFAULT_DATE_FORMAT_EXPLAIN' => 'The date format is the same as the PHP <code>date</code> function.',
@ -452,6 +454,8 @@ $lang = array_merge($lang, array(
'ALL' => 'All', 'ALL' => 'All',
'ALLOW_AUTOLOGIN' => 'Allow "Remember Me" logins', 'ALLOW_AUTOLOGIN' => 'Allow "Remember Me" logins',
'ALLOW_AUTOLOGIN_EXPLAIN' => 'Determines whether users are given "Remember Me" option when they visit the board.', 'ALLOW_AUTOLOGIN_EXPLAIN' => 'Determines whether users are given "Remember Me" option when they visit the board.',
'ALLOW_PASSWORD_RESET' => 'Allow password reset ("Forgot Password")',
'ALLOW_PASSWORD_RESET_EXPLAIN' => 'Determines whether or not users are able to use the "I forgot my password" link on the login page to recover their account. If you use an external authentication mechanism you may wish to disable this feature.',
'AUTOLOGIN_LENGTH' => '"Remember Me" login key expiration length (in days)', 'AUTOLOGIN_LENGTH' => '"Remember Me" login key expiration length (in days)',
'AUTOLOGIN_LENGTH_EXPLAIN' => 'Number of days after which "Remember Me" login keys are removed or zero to disable.', 'AUTOLOGIN_LENGTH_EXPLAIN' => 'Number of days after which "Remember Me" login keys are removed or zero to disable.',
'BROWSER_VALID' => 'Validate browser', 'BROWSER_VALID' => 'Validate browser',

View file

@ -51,7 +51,7 @@ $lang = array_merge($lang, array(
'LAST_ACTIVE_EXPLAIN' => 'Enter a date in <kbd>YYYY-MM-DD</kbd> format. Enter <kbd>0000-00-00</kbd> to prune users who never logged in, <em>Before</em> and <em>After</em> conditions will be ignored.', 'LAST_ACTIVE_EXPLAIN' => 'Enter a date in <kbd>YYYY-MM-DD</kbd> format. Enter <kbd>0000-00-00</kbd> to prune users who never logged in, <em>Before</em> and <em>After</em> conditions will be ignored.',
'POSTS_ON_QUEUE' => 'Posts Awaiting Approval', 'POSTS_ON_QUEUE' => 'Posts Awaiting Approval',
'PRUNE_USERS_GROUP_EXPLAIN' => 'Selects all members of the group for pruning.', 'PRUNE_USERS_GROUP_EXPLAIN' => 'Limit to users within the selected group.',
'PRUNE_USERS_LIST' => 'Users to be pruned', 'PRUNE_USERS_LIST' => 'Users to be pruned',
'PRUNE_USERS_LIST_DELETE' => 'With the selected critera for pruning users the following accounts will be removed. You can remove individual users from the deletion list by unchecking the box next to their username.', 'PRUNE_USERS_LIST_DELETE' => 'With the selected critera for pruning users the following accounts will be removed. You can remove individual users from the deletion list by unchecking the box next to their username.',
'PRUNE_USERS_LIST_DEACTIVATE' => 'With the selected critera for pruning users the following accounts will be deactivated. You can remove individual users from the deactivation list by unchecking the box next to their username.', 'PRUNE_USERS_LIST_DEACTIVATE' => 'With the selected critera for pruning users the following accounts will be deactivated. You can remove individual users from the deactivation list by unchecking the box next to their username.',

View file

@ -46,4 +46,5 @@ $lang = array_merge($lang, array(
'RECAPTCHA_PRIVATE_EXPLAIN' => 'Your private reCaptcha key. Keys can be obtained on <a href="http://www.google.com/recaptcha">www.google.com/recaptcha</a>.', 'RECAPTCHA_PRIVATE_EXPLAIN' => 'Your private reCaptcha key. Keys can be obtained on <a href="http://www.google.com/recaptcha">www.google.com/recaptcha</a>.',
'RECAPTCHA_EXPLAIN' => 'In an effort to prevent automatic submissions, we require that you enter both of the words displayed into the text field underneath.', 'RECAPTCHA_EXPLAIN' => 'In an effort to prevent automatic submissions, we require that you enter both of the words displayed into the text field underneath.',
'RECAPTCHA_SOCKET_ERROR' => 'There was a problem connecting to the RECAPTCHA service: could not open socket. Try again later.',
)); ));

View file

@ -313,6 +313,7 @@ $lang = array_merge($lang, array(
'IN' => 'in', 'IN' => 'in',
'INDEX' => 'Index page', 'INDEX' => 'Index page',
'INFORMATION' => 'Information', 'INFORMATION' => 'Information',
'INSECURE_REDIRECT' => 'Tried to redirect to potentially insecure url.',
'INTERESTS' => 'Interests', 'INTERESTS' => 'Interests',
'INVALID_DIGEST_CHALLENGE' => 'Invalid digest challenge.', 'INVALID_DIGEST_CHALLENGE' => 'Invalid digest challenge.',
'INVALID_EMAIL_LOG' => '<strong>%s</strong> possibly an invalid email address?', 'INVALID_EMAIL_LOG' => '<strong>%s</strong> possibly an invalid email address?',
@ -454,6 +455,7 @@ $lang = array_merge($lang, array(
'NO_POSTS_TIME_FRAME' => 'No posts exist inside this topic for the selected time frame.', 'NO_POSTS_TIME_FRAME' => 'No posts exist inside this topic for the selected time frame.',
'NO_FEED_ENABLED' => 'Feeds are not available on this board.', 'NO_FEED_ENABLED' => 'Feeds are not available on this board.',
'NO_FEED' => 'The requested feed is not available.', 'NO_FEED' => 'The requested feed is not available.',
'NO_STYLE_DATA' => 'Could not get style data',
'NO_SUBJECT' => 'No subject specified', // Used for posts having no subject defined but displayed within management pages. 'NO_SUBJECT' => 'No subject specified', // Used for posts having no subject defined but displayed within management pages.
'NO_SUCH_SEARCH_MODULE' => 'The specified search backend doesnt exist.', 'NO_SUCH_SEARCH_MODULE' => 'The specified search backend doesnt exist.',
'NO_SUPPORTED_AUTH_METHODS' => 'No supported authentication methods.', 'NO_SUPPORTED_AUTH_METHODS' => 'No supported authentication methods.',

View file

@ -10,5 +10,4 @@ If you want to view the post, click the following link:
If you want to view the topic, click the following link: If you want to view the topic, click the following link:
{U_VIEW_TOPIC} {U_VIEW_TOPIC}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -8,5 +8,4 @@ The following reason was given for the disapproval:
{REASON} {REASON}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -1,4 +1,4 @@
Subject: Topic reply notification - "{TOPIC_TITLE}" Subject: Post moderation notification - "{TOPIC_TITLE}"
Hello {USERNAME}, Hello {USERNAME},
@ -10,8 +10,4 @@ If you want to view the post, click the following link:
If you want to view the topic, click the following link: If you want to view the topic, click the following link:
{U_TOPIC} {U_TOPIC}
If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
{U_NOTIFICATION_SETTINGS}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -4,5 +4,4 @@ Hello {USERNAME},
You are receiving this notification because the report you filed on the post "{POST_SUBJECT}" in "{TOPIC_TITLE}" at "{SITENAME}" was handled by a moderator or by an administrator. The report was afterwards closed. If you have further questions contact {CLOSER_NAME} with a personal message. You are receiving this notification because the report you filed on the post "{POST_SUBJECT}" in "{TOPIC_TITLE}" at "{SITENAME}" was handled by a moderator or by an administrator. The report was afterwards closed. If you have further questions contact {CLOSER_NAME} with a personal message.
{EMAIL_SIG}
{EMAIL_SIG}

View file

@ -4,5 +4,4 @@ Hello {USERNAME},
You are receiving this notification because the report you filed on the post "{POST_SUBJECT}" in "{TOPIC_TITLE}" at "{SITENAME}" was deleted by a moderator or by an administrator. You are receiving this notification because the report you filed on the post "{POST_SUBJECT}" in "{TOPIC_TITLE}" at "{SITENAME}" was deleted by a moderator or by an administrator.
{EMAIL_SIG}
{EMAIL_SIG}

View file

@ -1,4 +1,4 @@
Subject: Topic reply notification - "{TOPIC_TITLE}" Subject: Private Message report - "{TOPIC_TITLE}"
Hello {USERNAME}, Hello {USERNAME},
@ -7,8 +7,4 @@ You are receiving this notification because a Private Message titled "{SUBJECT}"
If you want to view the report, click the following link: If you want to view the report, click the following link:
{U_VIEW_REPORT} {U_VIEW_REPORT}
If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
{U_NOTIFICATION_SETTINGS}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -1,4 +1,4 @@
Subject: Topic reply notification - "{TOPIC_TITLE}" Subject: Post report - "{TOPIC_TITLE}"
Hello {USERNAME}, Hello {USERNAME},
@ -10,8 +10,4 @@ If you want to view the report, click the following link:
If you want to view the post, click the following link: If you want to view the post, click the following link:
{U_VIEW_POST} {U_VIEW_POST}
If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
{U_NOTIFICATION_SETTINGS}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -10,5 +10,4 @@ If you want to view the post, click the following link:
If you want to view the topic, click the following link: If you want to view the topic, click the following link:
{U_VIEW_TOPIC} {U_VIEW_TOPIC}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -8,5 +8,4 @@ The following reason was given for the disapproval:
{REASON} {REASON}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -1,4 +1,4 @@
Subject: Topic reply notification - "{TOPIC_TITLE}" Subject: Post moderation notification - "{TOPIC_TITLE}"
Hello {USERNAME}, Hello {USERNAME},
@ -10,8 +10,4 @@ If you want to view the post, click the following link:
If you want to view the topic, click the following link: If you want to view the topic, click the following link:
{U_TOPIC} {U_TOPIC}
If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
{U_NOTIFICATION_SETTINGS}
{EMAIL_SIG} {EMAIL_SIG}

View file

@ -1,4 +1,4 @@
Subject: Topic reply notification - "{TOPIC_TITLE}" Subject: Private Message report - "{TOPIC_TITLE}"
Hello {USERNAME}, Hello {USERNAME},
@ -7,8 +7,4 @@ You are receiving this notification because a Private Message titled "{SUBJECT}"
If you want to view the report, click the following link: If you want to view the report, click the following link:
{U_VIEW_REPORT} {U_VIEW_REPORT}
If you no longer wish to receive updates about replies to bookmarks, please update your notification settings here:
{U_NOTIFICATION_SETTINGS}
{EMAIL_SIG} {EMAIL_SIG}

Some files were not shown because too many files have changed in this diff Show more