diff options
23 files changed, 158 insertions, 2187 deletions
diff --git a/.travis.yml b/.travis.yml index ecaf43c4b5..1e5f453c76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,10 @@ php: - 5.3 - 5.4 - 5.5 + - 5.6 env: - - DB=mariadb - DB=mysql - - DB=postgres before_script: - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi" @@ -24,10 +23,11 @@ before_script: script: - sh -c "if [ '$TRAVIS_PHP_VERSION' = '5.2' ]; then phpunit --configuration travis/phpunit-$DB-travis.xml; else phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml; fi" - -notifications: - email: - recipients: - - dev-team@phpbb.com - on_success: change - on_failure: change + - sh -c "if [ '$TRAVIS_PHP_VERSION' = '5.5' -a '$DB' = 'mysql' -a '$TRAVIS_PULL_REQUEST' != 'false' ]; then git-tools/commit-msg-hook-range.sh origin/$TRAVIS_BRANCH..FETCH_HEAD; fi" + +matrix: + include: + - php: 5.4 + env: DB=mariadb + - php: 5.4 + env: DB=postgres diff --git a/build/build.xml b/build/build.xml index 018f7b91a2..83ddcd29c4 100644 --- a/build/build.xml +++ b/build/build.xml @@ -105,7 +105,7 @@ <property name="dir" value="build/old_versions/release-${version}" /> </phingcall> - <exec dir="build/old_versions" command="diff -crNEBwd release-${version} release-${newversion} > + <exec dir="build/old_versions" command="LC_ALL=C diff -crNEBwd release-${version} release-${newversion} > ../new_version/patches/phpBB-${version}_to_${newversion}.patch" escape="false" /> </target> @@ -131,24 +131,22 @@ <target name="package" depends="clean,prepare,prepare-new-version,old-version-diffs"> <exec dir="build" command="php -f package.php '${versions}' > logs/package.log" escape="false" /> - <exec dir="build" command="php -f build_diff.php '${prevversion}' '${newversion}' > logs/build_diff.log" escape="false" /> - <exec dir="build" escape="false" command="diff -crNEBwd old_versions/release-${prevversion}/language new_version/phpBB3/language > - save/save_${prevversion}_to_${newversion}/language/phpbb-${prevversion}_to_${newversion}_language.patch" /> + save/phpbb-${prevversion}_to_${newversion}_language.patch" /> <exec dir="build" escape="false" command="diff -crNEBwd old_versions/release-${prevversion}/styles/prosilver new_version/phpBB3/styles/prosilver > - save/save_${prevversion}_to_${newversion}/prosilver/phpbb-${prevversion}_to_${newversion}_prosilver.patch" /> + save/phpbb-${prevversion}_to_${newversion}_prosilver.patch" /> <exec dir="build" escape="false" command="diff -crNEBwd old_versions/release-${prevversion}/styles/subsilver2 new_version/phpBB3/styles/subsilver2 > - save/save_${prevversion}_to_${newversion}/subsilver2/phpbb-${prevversion}_to_${newversion}_subsilver2.patch" /> + save/phpbb-${prevversion}_to_${newversion}_subsilver2.patch" /> <exec dir="build" escape="false" command="git shortlog --summary --numbered release-${prevversion}...HEAD > - save/save_${prevversion}_to_${newversion}/phpbb-${prevversion}_to_${newversion}_git_shortlog.txt" /> + save/phpbb-${prevversion}_to_${newversion}_git_shortlog.txt" /> <exec dir="build" escape="false" command="git diff --stat release-${prevversion}...HEAD > - save/save_${prevversion}_to_${newversion}/phpbb-${prevversion}_to_${newversion}_git_diffstat.txt" /> + save/phpbb-${prevversion}_to_${newversion}_git_diffstat.txt" /> <phingcall target="checksum-dir"> <property name="dir" value="build/new_version/release_files" /> diff --git a/build/build_diff.php b/build/build_diff.php deleted file mode 100755 index d264ecf493..0000000000 --- a/build/build_diff.php +++ /dev/null @@ -1,411 +0,0 @@ -#!/usr/bin/env php -<?php -/** -* -* @package build -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -if ($_SERVER['argc'] != 3) -{ - die("Please specify the previous and current version as arguments (e.g. build_diff.php '1.0.2' '1.0.3')."); -} - -$old_version = trim($_SERVER['argv'][1]); -$new_version = trim($_SERVER['argv'][2]); - -$substitute_old = $old_version; -$substitute_new = $new_version; -$simple_name_old = 'release-' . $old_version; -$simple_name_new = 'release-' . $new_version; -$echo_changes = false; - -// DO NOT EVER USE THE FOLLOWING! Fix the script to generate proper changes, -// do NOT manually create them. - -// Set this to true to just compress the changes and do not build them again -// This should be used for building custom modified txt file. ;) -$package_changed_files = false; - -//$debug_file = 'includes/functions_user.php'; //'styles/prosilver/style.cfg'; -$debug_file = false; - -if ($debug_file !== false) -{ - $echo_changes = false; -} - -$s_name = 'save_' . $substitute_old . '_to_' . $substitute_new; - -$location = dirname(__FILE__); - -if (!$package_changed_files) -{ - if (!$echo_changes) - { - // Create directory... - run_command("mkdir $location/save/{$s_name}"); - run_command("mkdir $location/save/{$s_name}/language"); - run_command("mkdir $location/save/{$s_name}/prosilver"); - run_command("mkdir $location/save/{$s_name}/subsilver2"); - } -} - -// Build code changes and place them into 'save' -if (!$package_changed_files) -{ - build_code_changes('language'); - build_code_changes('prosilver'); - build_code_changes('subsilver2'); -} - -// Package code changes -$code_changes_filename = 'phpBB-' . $substitute_old . '_to_' . $substitute_new . '-codechanges'; - -if (!$echo_changes) -{ - // Now compress the files... - // Build Main phpBB Release - $compress_programs = array( -// 'tar.gz' => 'tar -czf', - 'tar.bz2' => 'tar -cjf', - 'zip' => 'zip -r' - ); - - chdir($location . '/save/' . $s_name); - foreach ($compress_programs as $extension => $compress_command) - { - echo "Packaging code changes for $extension\n"; - run_command("rm ./../../new_version/release_files/{$code_changes_filename}.{$extension}"); - flush(); - - // Build Package - run_command("$compress_command ./../../new_version/release_files/{$code_changes_filename}.{$extension} *"); - flush(); - } -} - -/** -* $output_format can be: language, prosilver and subsilver2 -*/ -function build_code_changes($output_format) -{ - global $substitute_new, $substitute_old, $simple_name_old, $simple_name_new, $echo_changes, $package_changed_files, $location, $debug_file, $s_name; - - // Global array holding the data entries - $data = array( - 'header' => array(), - 'diff' => array(), - ); - - // Read diff file and prepare the output filedata... - //$patch_filename = '../new_version/patches/phpBB-' . $substitute_old . '_to_' . $substitute_new . '.patch'; - $release_filename = 'phpbb-' . $substitute_old . '_to_' . $substitute_new . '_' . $output_format . '.txt'; - - if (!$package_changed_files) - { - if (!$echo_changes) - { - $fp = fopen('save/' . $s_name . '/' . $output_format . '/' . $release_filename, 'wb'); - - if (!$fp) - { - die('Unable to create ' . $release_filename); - } - } - } - - include_once($location . '/build_helper.php'); - $package = new build_package(array($substitute_old, $substitute_new), false); - - $titles = array( - 'language' => 'phpBB ' . $substitute_old . ' to phpBB ' . $substitute_new . ' Language Pack Changes', - 'prosilver' => 'phpBB ' . $substitute_old . ' to phpBB ' . $substitute_new . ' prosilver Changes', - 'subsilver2' => 'phpBB ' . $substitute_old . ' to phpBB ' . $substitute_new . ' subsilver2 Changes', - ); - - $data['header'] = array( - 'title' => $titles[$output_format], - 'intro' => ' - -These are the ' . $titles[$output_format] . ' summed up into a little Mod. These changes are only partial and do not include any code changes, therefore not meant for updating phpBB. - - ', - 'included_files' => array(), - ); - - // We collect the files we want to diff first (ironically we grab this from a diff file) - if (!$echo_changes) - { - echo "\n\nCollecting Filenames:"; - } - - // We re-create the patch file - foreach ($package->old_packages as $_package_name => $dest_package_filename) - { - chdir($package->locations['old_versions']); - - if (!$echo_changes) - { - echo "\n\n" . 'Creating patch/diff files for phpBB-' . $dest_package_filename . $package->get('new_version_number'); - } - - $dest_package_filename = $location . '/save/' . $s_name . '/phpBB-' . $dest_package_filename . $package->get('new_version_number') . '.patch'; - $package->run_command('diff ' . $package->diff_options . ' ' . $_package_name . ' ' . $package->get('simple_name') . ' > ' . $dest_package_filename); - - // Parse this diff to determine file changes from the checked versions and save them - $result = $package->collect_diff_files($dest_package_filename, $_package_name); - $package->run_command('rm ' . $dest_package_filename); - } - - chdir($location); - - $filenames = array(); - foreach ($result['files'] as $filename) - { - if ($debug_file !== false && $filename != $debug_file) - { - continue; - } - - // Decide which files to compare... - switch ($output_format) - { - case 'language': - if (strpos($filename, 'language/en/') !== 0) - { - continue 2; - } - break; - - case 'prosilver': - if (strpos($filename, 'styles/prosilver/') !== 0) - { - continue 2; - } - break; - - case 'subsilver2': - if (strpos($filename, 'styles/subsilver2/') !== 0) - { - continue 2; - } - break; - } - - if (!file_exists($location . '/old_versions/' . $simple_name_old . '/' . $filename)) - { - // New file... include it - $data['header']['included_files'][] = array( - 'old' => $location . '/old_versions/' . $simple_name_old . '/' . $filename, - 'new' => $location . '/old_versions/' . $simple_name_new . '/' . $filename, - 'phpbb_filename' => $filename, - ); - continue; - } - - $filenames[] = array( - 'old' => $location . '/old_versions/' . $simple_name_old . '/' . $filename, - 'new' => $location . '/old_versions/' . $simple_name_new . '/' . $filename, - 'phpbb_filename' => $filename, - ); - } - - // Now let us go through the filenames list and create a more comprehensive diff - if (!$echo_changes) - { - fwrite($fp, build_header($output_format, $filenames, $data['header'])); - } - else - { - //echo build_header('text', $filenames, $data['header']); - } - - // Copy files... - $files_to_copy = array(); - - foreach ($data['header']['included_files'] as $filename) - { - $files_to_copy[] = $filename['phpbb_filename']; - } - - // First step is to copy the new version over (clean structure) - if (!$echo_changes && sizeof($files_to_copy)) - { - foreach ($files_to_copy as $file) - { - // Create directory? - $dirname = dirname($file); - - if ($dirname) - { - $dirname = explode('/', $dirname); - $__dir = array(); - - foreach ($dirname as $i => $dir) - { - $__dir[] = $dir; - run_command("mkdir -p $location/save/" . $s_name . '/' . $output_format . '/' . implode('/', $__dir)); - } - } - - $source_file = $location . '/new_version/phpBB3/' . $file; - $dest_file = $location . '/save/' . $s_name . '/' . $output_format . '/'; - $dest_file .= $file; - - $command = "cp -p $source_file $dest_file"; - $result = trim(`$command`); - echo "- Copied File: " . $source_file . " -> " . $dest_file . "\n"; - } - } - - include_once('diff_class.php'); - - if (!$echo_changes) - { - echo "\n\nDiffing Codebases:"; - } - - foreach ($filenames as $file_ary) - { - if (!file_exists($file_ary['old'])) - { - $lines1 = array(); - } - else - { - $lines1 = file($file_ary['old']); - } - $lines2 = file($file_ary['new']); - - if (!sizeof($lines1)) - { - // New File - } - else - { - $diff = new Diff($lines1, $lines2); - $fmt = new BBCodeDiffFormatter(false, 5, $debug_file); - - if (!$echo_changes) - { - fwrite($fp, $fmt->format_open($file_ary['phpbb_filename'])); - fwrite($fp, $fmt->format($diff, $lines1)); - fwrite($fp, $fmt->format_close($file_ary['phpbb_filename'])); - } - else - { - echo $fmt->format_open($file_ary['phpbb_filename']); - echo $fmt->format($diff, $lines1); - echo $fmt->format_close($file_ary['phpbb_filename']); - } - - if ($debug_file !== false) - { - echo $fmt->format_open($file_ary['phpbb_filename']); - echo $fmt->format($diff, $lines1); - echo $fmt->format_close($file_ary['phpbb_filename']); - exit; - } - } - } - - if (!$echo_changes) - { - fwrite($fp, build_footer($output_format)); - - // Close file - fclose($fp); - - chmod('save/' . $s_name . '/' . $output_format . '/' . $release_filename, 0666); - } - else - { - echo build_footer($output_format); - } -} - -/** -* Build Footer -*/ -function build_footer($mode) -{ - $html = ''; - - $html .= "# \n"; - $html .= "#-----[ SAVE/CLOSE ALL FILES ]------------------------------------------ \n"; - $html .= "# \n"; - $html .= "# EoM"; - - return $html; -} - -/** -* Build Header -*/ -function build_header($mode, $filenames, $header) -{ - global $substitute_old; - - $html = ''; - - $html .= "############################################################## \n"; - $html .= "## Title: " . $header['title'] . "\n"; - $html .= "## Author: naderman < naderman@phpbb.com > (Nils Adermann) http://www.phpbb.com \n"; - $html .= "## Description: \n"; - - $intr = explode("\n", $header['intro']); - $introduction = ''; - foreach ($intr as $_line) - { - $introduction .= wordwrap($_line, 80) . "\n"; - } - $intr = explode("\n", $introduction); - - foreach ($intr as $_line) - { - $html .= "## " . $_line . "\n"; - } - $html .= "## \n"; - $html .= "## Files To Edit: \n"; - - foreach ($filenames as $file_ary) - { - $html .= "## " . $file_ary['phpbb_filename'] . "\n"; - } - $html .= "##\n"; - if (sizeof($header['included_files'])) - { - $html .= "## Included Files: \n"; - foreach ($header['included_files'] as $filename) - { - $html .= "## {$filename['phpbb_filename']}\n"; - } - } - $html .= "## License: http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 \n"; - $html .= "############################################################## \n"; - $html .= "\n"; - - // COPY Statement? - if (sizeof($header['included_files'])) - { - $html .= "#\n#-----[ COPY ]------------------------------------------\n#\n"; - foreach ($header['included_files'] as $filename) - { - $html .= "copy {$filename['phpbb_filename']} to {$filename['phpbb_filename']}\n"; - } - $html .= "\n"; - } - - return $html; -} - -function run_command($command) -{ - $result = trim(`$command`); - echo "\n- Command Run: " . $command . "\n"; -} - -?> diff --git a/build/diff_class.php b/build/diff_class.php deleted file mode 100644 index 2d8555400d..0000000000 --- a/build/diff_class.php +++ /dev/null @@ -1,1710 +0,0 @@ -<?php -/** -* -* @package build -* @copyright (c) 2000 Geoffrey T. Dairiki <dairiki@dairiki.org> -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* Class used internally by WikiDiff to actually compute the diffs. -* -* The algorithm used here is mostly lifted from the perl module -* Algorithm::Diff (version 1.06) by Ned Konz, which is available at: -* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip -* -* More ideas are taken from: -* http://www.ics.uci.edu/~eppstein/161/960229.html -* -* Some ideas are (and a bit of code) are from from analyze.c, from GNU -* diffutils-2.7, which can be found at: -* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz -* -* Finally, some ideas (subdivision by NCHUNKS > 2, and some optimizations) -* are my own. -*/ -class _WikiDiffEngine -{ - var $edits; // List of editing operation to convert XV to YV. - var $xv = array(), $yv = array(); - - function _WikiDiffEngine($from_lines, $to_lines) - { - $n_from = sizeof($from_lines); - $n_to = sizeof($to_lines); - - $endskip = 0; - // Ignore trailing and leading matching lines. - while ($n_from > 0 && $n_to > 0) - { - if ($from_lines[$n_from - 1] != $to_lines[$n_to - 1]) - { - break; - } - - $n_from--; - $n_to--; - $endskip++; - } - - for ($skip = 0; $skip < min($n_from, $n_to); $skip++) - { - if ($from_lines[$skip] != $to_lines[$skip]) - { - break; - } - } - $n_from -= $skip; - $n_to -= $skip; - - $xlines = array(); - $ylines = array(); - - // Ignore lines which do not exist in both files. - for ($x = 0; $x < $n_from; $x++) - { - $xhash[$from_lines[$x + $skip]] = 1; - } - - for ($y = 0; $y < $n_to; $y++) - { - $line = $to_lines[$y + $skip]; - $ylines[] = $line; - - if (($this->ychanged[$y] = empty($xhash[$line]))) - { - continue; - } - $yhash[$line] = 1; - $this->yv[] = $line; - $this->yind[] = $y; - } - - for ($x = 0; $x < $n_from; $x++) - { - $line = $from_lines[$x + $skip]; - $xlines[] = $line; - - if (($this->xchanged[$x] = empty($yhash[$line]))) - { - continue; // fixme? what happens to yhash/xhash when - // there are two identical lines?? - } - $this->xv[] = $line; - $this->xind[] = $x; - } - - // Find the LCS. - $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); - - // Merge edits when possible - $this->_shift_boundaries($xlines, $this->xchanged, $this->ychanged); - $this->_shift_boundaries($ylines, $this->ychanged, $this->xchanged); - - // Compute the edit operations. - $this->edits = array(); - - if ($skip) - { - $this->edits[] = $skip; - } - - $x = 0; - $y = 0; - - while ($x < $n_from || $y < $n_to) - { - // Skip matching "snake". - $x0 = $x; - $ncopy = 0; - while ($x < $n_from && $y < $n_to && !$this->xchanged[$x] && !$this->ychanged[$y]) - { - ++$x; - ++$y; - ++$ncopy; - } - - if ($x > $x0) - { - $this->edits[] = $x - $x0; - } - - // Find deletes. - $x0 = $x; - $ndelete = 0; - - while ($x < $n_from && $this->xchanged[$x]) - { - ++$x; - ++$ndelete; - } - - if ($x > $x0) - { - $this->edits[] = -($x - $x0); - } - - // Find adds. - if (isset($this->ychanged[$y]) && $this->ychanged[$y]) - { - $adds = array(); - while ($y < $n_to && $this->ychanged[$y]) - { - $adds[] = $ylines[$y++]; - } - $this->edits[] = $adds; - } - } - - if (!empty($endskip)) - { - $this->edits[] = $endskip; - } - } - - /* Divide the Largest Common Subsequence (LCS) of the sequences - * [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally - * sized segments. - * - * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an - * array of NCHUNKS+1 (X, Y) indexes giving the diving points between - * sub sequences. The first sub-sequence is contained in [X0, X1), - * [Y0, Y1), the second in [X1, X2), [Y1, Y2) and so on. Note - * that (X0, Y0) == (XOFF, YOFF) and - * (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). - * - * This function assumes that the first lines of the specified portions - * of the two files do not match, and likewise that the last lines do not - * match. The caller must trim matching lines from the beginning and end - * of the portions it is going to specify. - */ - function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) - { - $flip = false; - - if ($xlim - $xoff > $ylim - $yoff) - { - // Things seems faster (I'm not sure I understand why) - // when the shortest sequence in X. - $flip = true; - list ($xoff, $xlim, $yoff, $ylim) = array( $yoff, $ylim, $xoff, $xlim); - } - - if ($flip) - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->xv[$i]][] = $i; - } - } - else - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->yv[$i]][] = $i; - } - } - - $this->lcs = 0; - $this->seq[0]= $yoff - 1; - $this->in_seq = array(); - $ymids[0] = array(); - - $numer = $xlim - $xoff + $nchunks - 1; - $x = $xoff; - - for ($chunk = 0; $chunk < $nchunks; $chunk++) - { - if ($chunk > 0) - { - for ($i = 0; $i <= $this->lcs; $i++) - { - $ymids[$i][$chunk-1] = $this->seq[$i]; - } - } - - $x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks); - - for ( ; $x < $x1; $x++) - { - $_index = $flip ? $this->yv[$x] : $this->xv[$x]; - $matches = (isset($ymatches[$_index])) ? $ymatches[$_index] : array(); - - if (!$matches) - { - continue; - } - reset($matches); - - while (list ($junk, $y) = each($matches)) - { - if (!isset($this->in_seq[$y]) || !$this->in_seq[$y]) - { - $k = $this->_lcs_pos($y); - //if (!$k) die('assertion "!$k" failed'); - $ymids[$k] = $ymids[$k-1]; - break; - } - } - - while (list ($junk, $y) = each($matches)) - { - if ($y > $this->seq[$k-1]) - { - //if ($y >= $this->seq[$k]) die('assertion failed'); - // Optimization: this is a common case: - // next match is just replacing previous match. - $this->in_seq[$this->seq[$k]] = false; - $this->seq[$k] = $y; - $this->in_seq[$y] = 1; - } - else if (!isset($this->in_seq[$y]) || !$this->in_seq[$y]) - { - $k = $this->_lcs_pos($y); - //if (!$k) die('assertion "!$k" failed'); - $ymids[$k] = $ymids[$k-1]; - } - } - } - } - - $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); - $ymid = $ymids[$this->lcs]; - - for ($n = 0; $n < $nchunks - 1; $n++) - { - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); - $y1 = $ymid[$n] + 1; - $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); - } - $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); - - return array($this->lcs, $seps); - } - - function _lcs_pos ($ypos) - { - $end = $this->lcs; - if ($end == 0 || $ypos > $this->seq[$end]) - { - $this->seq[++$this->lcs] = $ypos; - $this->in_seq[$ypos] = 1; - return $this->lcs; - } - - $beg = 1; - while ($beg < $end) - { - $mid = (int)(($beg + $end) / 2); - - if ($ypos > $this->seq[$mid]) - { - $beg = $mid + 1; - } - else - { - $end = $mid; - } - } - - //if ($ypos == $this->seq[$end]) die("assertion failure"); - - $this->in_seq[$this->seq[$end]] = false; - $this->seq[$end] = $ypos; - $this->in_seq[$ypos] = 1; - return $end; - } - - /* Find LCS of two sequences. - * - * The results are recorded in the vectors $this->{x,y}changed[], by - * storing a 1 in the element for each line that is an insertion - * or deletion (ie. is not in the LCS). - * - * The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. - * - * Note that XLIM, YLIM are exclusive bounds. - * All line numbers are origin-0 and discarded lines are not counted. - */ - function _compareseq ($xoff, $xlim, $yoff, $ylim) - { - // Slide down the bottom initial diagonal. - while ($xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff]) - { - ++$xoff; - ++$yoff; - } - - // Slide up the top initial diagonal. - while ($xlim > $xoff && $ylim > $yoff && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) - { - --$xlim; - --$ylim; - } - - if ($xoff == $xlim || $yoff == $ylim) - { - $lcs = 0; - } - else - { - // This is ad hoc but seems to work well. - //$nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); - //$nchunks = max(2,min(8,(int)$nchunks)); - $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; - list ($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); - } - - if ($lcs == 0) - { - // X and Y sequences have no common subsequence: - // mark all changed. - while ($yoff < $ylim) - { - $this->ychanged[$this->yind[$yoff++]] = 1; - } - - while ($xoff < $xlim) - { - $this->xchanged[$this->xind[$xoff++]] = 1; - } - } - else - { - // Use the partitions to split this problem into subproblems. - reset($seps); - - $pt1 = $seps[0]; - - while ($pt2 = next($seps)) - { - $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]); - $pt1 = $pt2; - } - } - } - - /* Adjust inserts/deletes of identical lines to join changes - * as much as possible. - * - * We do something when a run of changed lines include a - * line at one end and have an excluded, identical line at the other. - * We are free to choose which identical line is included. - * `compareseq' usually chooses the one at the beginning, - * but usually it is cleaner to consider the following identical line - * to be the "change". - * - * This is extracted verbatim from analyze.c (GNU diffutils-2.7). - */ - function _shift_boundaries ($lines, &$changed, $other_changed) - { - $i = 0; - $j = 0; - $len = sizeof($lines); - - while (1) - { - /* - * Scan forwards to find beginning of another run of changes. - * Also keep track of the corresponding point in the other file. - */ - - while ($i < $len && $changed[$i] == 0) - { - while ($other_changed[$j++]) - { - continue; - } - $i++; - } - - if ($i == $len) - { - break; - } - - $start = $i; - - // Find the end of this run of changes. - while (isset($changed[++$i])) - { - continue; - } - - while (isset($other_changed[$j]) && $other_changed[$j]) - { - $j++; - } - - do - { - /* - * Record the length of this run of changes, so that - * we can later determine whether the run has grown. - */ - $runlength = $i - $start; - - /* - * Move the changed region back, so long as the - * previous unchanged line matches the last changed one. - * This merges with previous changed regions. - */ - while ($start && $lines[$start - 1] == $lines[$i - 1]) - { - $changed[--$start] = 1; - $changed[--$i] = false; - - while ($changed[$start - 1]) - { - $start--; - } - - while ($other_changed[--$j]) - { - continue; - } - } - - /* - * Set CORRESPONDING to the end of the changed run, at the last - * point where it corresponds to a changed run in the other file. - * CORRESPONDING == LEN means no such point has been found. - */ - $corresponding = empty($other_changed[$j - 1]) ? $len : $i; - - /* - * Move the changed region forward, so long as the - * first changed line matches the following unchanged one. - * This merges with following changed regions. - * Do this second, so that if there are no merges, - * the changed region is moved forward as far as possible. - */ - while ($i != $len && $lines[$start] == $lines[$i]) - { - $changed[$start++] = false; - $changed[$i++] = 1; - - while ($changed[$i]) - { - $i++; - } - - while ($other_changed[++$j]) - { - $corresponding = $i; - } - } - } while ($runlength != $i - $start); - - /* - * If possible, move the fully-merged run of changes - * back to a corresponding run in the other file. - */ - while ($corresponding < $i) - { - $changed[--$start] = 1; - $changed[--$i] = 0; - - while ($other_changed[--$j]) - { - continue; - } - } - } - } -} - -/** -* Class representing a diff between two files. -*/ -class Diff -{ - var $edits; - - /** - * Compute diff between files (or deserialize serialized WikiDiff.) - */ - function Diff($from_lines = false, $to_lines = false) - { - if ($from_lines && $to_lines) - { - $compute = new _WikiDiffEngine($from_lines, $to_lines); - $this->edits = $compute->edits; - } - else if ($from_lines) - { - // $from_lines is not really from_lines, but rather - // a serialized Diff. - $this->edits = unserialize($from_lines); - } - else - { - $this->edits = array(); - } - } - - /** - * Compute reversed Diff. - * - * SYNOPSIS: - * - * $diff = new Diff($lines1, $lines2); - * $rev = $diff->reverse($lines1); - * - * // reconstruct $lines1 from $lines2: - * $out = $rev->apply($lines2); - */ - function reverse ($from_lines) - { - $x = 0; - $rev = new Diff; - - for (reset($this->edits); $edit = current($this->edits); next($this->edits)) - { - if (is_array($edit)) - { // Was an add, turn it into a delete. - $nadd = sizeof($edit); - if ($nadd == 0) - { - die("assertion error"); - } - $edit = -$nadd; - } - else if ($edit > 0) - { - // Was a copy --- just pass it through. } - $x += $edit; - } - else if ($edit < 0) - { // Was a delete, turn it into an add. - $ndelete = -$edit; - $edit = array(); - - while ($ndelete-- > 0) - { - $edit[] = $from_lines[$x++]; - } - } - else - { - die("assertion error"); - } - - $rev->edits[] = $edit; - } - - return $rev; - } - - /** - * Compose (concatenate) Diffs. - * - * SYNOPSIS: - * - * $diff1 = new Diff($lines1, $lines2); - * $diff2 = new Diff($lines2, $lines3); - * $comp = $diff1->compose($diff2); - * - * // reconstruct $lines3 from $lines1: - * $out = $comp->apply($lines1); - */ - function compose ($that) - { - reset($this->edits); - reset($that->edits); - - $comp = new Diff; - $left = current($this->edits); - $right = current($that->edits); - - while ($left || $right) - { - if (!is_array($left) && $left < 0) - { // Left op is a delete. - $newop = $left; - $left = next($this->edits); - } - else if (is_array($right)) - { // Right op is an add. - $newop = $right; - $right = next($that->edits); - } - else if (!$left || !$right) - { - die ("assertion error"); - } - else if (!is_array($left) && $left > 0) - { // Left op is a copy. - if ($left <= abs($right)) - { - $newop = $right > 0 ? $left : -$left; - $right -= $newop; - - if ($right == 0) - { - $right = next($that->edits); - } - $left = next($this->edits); - } - else - { - $newop = $right; - $left -= abs($right); - $right = next($that->edits); - } - } - else - { // Left op is an add. - if (!is_array($left)) - { - die('assertion error'); - } - $nleft = sizeof($left); - - if ($nleft <= abs($right)) - { - if ($right > 0) - { // Right op is copy - $newop = $left; - $right -= $nleft; - } - else // Right op is delete - { - $newop = false; - $right += $nleft; - } - - if ($right == 0) - { - $right = next($that->edits); - } - $left = next($this->edits); - } - else - { - unset($newop); - - if ($right > 0) - { - for ($i = 0; $i < $right; $i++) - { - $newop[] = $left[$i]; - } - } - - $tmp = array(); - for ($i = abs($right); $i < $nleft; $i++) - { - $tmp[] = $left[$i]; - } - $left = $tmp; - $right = next($that->edits); - } - } - - if (!$op) - { - $op = $newop; - continue; - } - - if (!$newop) - { - continue; - } - - if (is_array($op) && is_array($newop)) - { - // Both $op and $newop are adds. - for ($i = 0; $i < sizeof($newop); $i++) - { - $op[] = $newop[$i]; - } - } - else if (($op > 0 && $newop > 0) || ($op < 0 && $newop < 0)) - { // $op and $newop are both either deletes or copies. - $op += $newop; - } - else - { - $comp->edits[] = $op; - $op = $newop; - } - } - - if ($op) - { - $comp->edits[] = $op; - } - - return $comp; - } - - /* Debugging only: - function _dump () - { - echo "<ol>"; - for (reset($this->edits); - { - $edit = current($this->edits); - } - next($this->edits)) - { - echo "<li>"; - if ($edit > 0) - echo "Copy $edit"; - else if ($edit < 0) - echo "Delete " . -$edit; - else if (is_array($edit)) - { - echo "Add " . sizeof($edit) . "<ul>"; - for ($i = 0; $i < sizeof($edit); $i++) - echo "<li>" . htmlspecialchars($edit[$i]); - echo "</ul>"; - } - else - die("assertion error"); - } - echo "</ol>"; - } - */ - - /** - * Apply a Diff to a set of lines. - * - * SYNOPSIS: - * - * $diff = new Diff($lines1, $lines2); - * - * // reconstruct $lines2 from $lines1: - * $out = $diff->apply($lines1); - */ - function apply ($from_lines) - { - $x = 0; - $xlim = sizeof($from_lines); - - for (reset($this->edits); $edit = current($this->edits); next($this->edits)) - { - if (is_array($edit)) - { - reset($edit); - while (list ($junk, $line) = each($edit)) - { - $output[] = $line; - } - } - else if ($edit > 0) - { - while ($edit--) - { - $output[] = $from_lines[$x++]; - } - } - else - { - $x += -$edit; - } - } - - if ($x != $xlim) - { - die(sprintf("Diff::apply: line count mismatch: %s != %s", $x, $xlim)); - } - - return $output; - } - - /** - * Serialize a Diff. - * - * SYNOPSIS: - * - * $diff = new Diff($lines1, $lines2); - * $string = $diff->serialize; - * - * // recover Diff from serialized version: - * $diff2 = new Diff($string); - */ - function serialize () - { - return serialize($this->edits); - } - - /** - * Return true if two files were equal. - */ - function isEmpty() - { - if (sizeof($this->edits) > 1) - { - return false; - } - - if (sizeof($this->edits) == 0) - { - return true; - } - - // Test for: only edit is a copy. - return !is_array($this->edits[0]) && $this->edits[0] > 0; - } - - /** - * Compute the length of the Longest Common Subsequence (LCS). - * - * This is mostly for diagnostic purposed. - */ - function lcs() - { - $lcs = 0; - for (reset($this->edits); $edit = current($this->edits); next($this->edits)) - { - if (!is_array($edit) && $edit > 0) - { - $lcs += $edit; - } - } - - return $lcs; - } - - /** - * Check a Diff for validity. - * - * This is here only for debugging purposes. - */ - function _check ($from_lines, $to_lines) - { - $test = $this->apply($from_lines); - if (serialize($test) != serialize($to_lines)) - { - die("Diff::_check: failed"); - } - - reset($this->edits); - $prev = current($this->edits); - $prevtype = is_array($prev) ? 'a' : ($prev > 0 ? 'c' : 'd'); - - while ($edit = next($this->edits)) - { - $type = is_array($edit) ? 'a' : ($edit > 0 ? 'c' : 'd'); - if ($prevtype == $type) - { - die("Diff::_check: edit sequence is non-optimal"); - } - $prevtype = $type; - } - $lcs = $this->lcs(); - echo "<strong>Diff Okay: LCS = $lcs</strong>\n"; - } -} - -/** -* A class to format a Diff as HTML. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new DiffFormatter; -* echo $fmt->format($diff, $lines1); // Output HTMLified standard diff. -* -* or to output reverse diff (diff's that would take $lines2 to $lines1): -* -* $fmt = new DiffFormatter(true); -* echo $fmt->format($diff, $lines1); -*/ -class DiffFormatter -{ - var $context_lines; - var $do_reverse_diff; - var $context_prefix, $deletes_prefix, $adds_prefix; - - function DiffFormatter ($reverse = false) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = 0; - $this->context_prefix = ' '; - $this->deletes_prefix = '< '; - $this->adds_prefix = '> '; - } - - function format ($diff, $from_lines) - { - $html = '<table width="100%" bgcolor="black" cellspacing=2 cellpadding=2 border=0>' . "\n"; - $html .= $this->_format($diff->edits, $from_lines); - $html .= "</table>\n"; - - return $html; - } - - function _format ($edits, $from_lines) - { - $html = ''; - $x = 0; $y = 0; - $xlim = sizeof($from_lines); - - reset($edits); - while ($edit = current($edits)) - { - if (!is_array($edit) && $edit >= 0) - { // Edit op is a copy. - $ncopy = $edit; - } - else - { - $ncopy = 0; - - if (empty($hunk)) - { - // Start of an output hunk. - $xoff = max(0, $x - $this->context_lines); - $yoff = $xoff + $y - $x; - - if ($xoff < $x) - { - // Get leading context. - $context = array(); - - for ($i = $xoff; $i < $x; $i++) - { - $context[] = $from_lines[$i]; - } - $hunk['c'] = $context; - } - } - - if (is_array($edit)) - { - // Edit op is an add. - $y += sizeof($edit); - $hunk[$this->do_reverse_diff ? 'd' : 'a'] = $edit; - } - else - { - // Edit op is a delete - $deletes = array(); - - while ($edit++ < 0) - { - $deletes[] = $from_lines[$x++]; - } - - $hunk[$this->do_reverse_diff ? 'a' : 'd'] = $deletes; - } - } - - $next = next($edits); - - if (!empty($hunk)) - { - // Originally $ncopy > 2 * $this->context_lines, but we need to split as early as we can for creating MOD Text Templates. ;) - if (!$next || $ncopy > $this->context_lines) - { - // End of an output hunk. - $hunks[] = $hunk; - unset($hunk); - - $xend = min($x + $this->context_lines, $xlim); - - if ($x < $xend) - { - // Get trailing context. - $context = array(); - for ($i = $x; $i < $xend; $i++) - { - $context[] = $from_lines[$i]; - } - $hunks[] = array('c' => $context); - } - - $xlen = $xend - $xoff; - $ylen = $xend + $y - $x - $yoff; - $xbeg = $xlen ? $xoff + 1 : $xoff; - $ybeg = $ylen ? $yoff + 1 : $yoff; - - if ($this->do_reverse_diff) - { - list ($xbeg, $xlen, $ybeg, $ylen) = array($ybeg, $ylen, $xbeg, $xlen); - } - - $html .= $this->_emit_diff($xbeg, $xlen, $ybeg, $ylen, $hunks); - unset($hunks); - } - else if ($ncopy) - { - $hunks[] = $hunk; - - // Copy context. - $context = array(); - for ($i = $x; $i < $x + $ncopy; $i++) - { - $context[] = $from_lines[$i]; - } - $hunk = array('c' => $context); - } - } - - $x += $ncopy; - $y += $ncopy; - } - - return $html; - } - - function _emit_lines($lines, $prefix, $color) - { - $html = ''; - reset($lines); - while (list ($junk, $line) = each($lines)) - { - $html .= "<tr bgcolor=\"$color\"><td><tt>$prefix</tt>"; - $html .= "<tt>" . htmlspecialchars($line) . "</tt></td></tr>\n"; - } - return $html; - } - - function _emit_diff ($xbeg,$xlen,$ybeg,$ylen,$hunks) - { - // Save hunk... - $this->diff_hunks[] = $hunks; - - $html = '<tr><td><table width="100%" bgcolor="white" cellspacing="0" border="0" cellpadding="4"> - <tr bgcolor="#cccccc"><td><tt>' . - $this->_diff_header($xbeg, $xlen, $ybeg, $ylen) . ' - </tt></td></tr>\n<tr><td> - <table width="100%" cellspacing="0" border="0" cellpadding="2"> - '; - - $prefix = array('c' => $this->context_prefix, 'a' => $this->adds_prefix, 'd' => $this->deletes_prefix); - $color = array('c' => '#ffffff', 'a' => '#ffcccc', 'd' => '#ccffcc'); - - for (reset($hunks); $hunk = current($hunks); next($hunks)) - { - if (!empty($hunk['c'])) - { - $html .= $this->_emit_lines($hunk['c'], $this->context_prefix, '#ffffff'); - } - - if (!empty($hunk['d'])) - { - $html .= $this->_emit_lines($hunk['d'], $this->deletes_prefix, '#ccffcc'); - } - - if (!empty($hunk['a'])) - { - $html .= $this->_emit_lines($hunk['a'], $this->adds_prefix, '#ffcccc'); - } - } - - $html .= "</table></td></tr></table></td></tr>\n"; - return $html; - } - - function _diff_header ($xbeg,$xlen,$ybeg,$ylen) - { - $what = $xlen ? ($ylen ? 'c' : 'd') : 'a'; - $xlen = $xlen > 1 ? "," . ($xbeg + $xlen - 1) : ''; - $ylen = $ylen > 1 ? "," . ($ybeg + $ylen - 1) : ''; - - return "$xbeg$xlen$what$ybeg$ylen"; - } -} - -/** -* A class to format a Diff as a pretty HTML unified diff. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new UnifiedDiffFormatter; -* echo $fmt->format($diff, $lines1); // Output HTMLified unified diff. -*/ -class UnifiedDiffFormatter extends DiffFormatter -{ - function UnifiedDiffFormatter ($reverse = false, $context_lines = 3) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = $context_lines; - $this->context_prefix = ' '; - $this->deletes_prefix = '-'; - $this->adds_prefix = '+'; - } - - function _diff_header ($xbeg,$xlen,$ybeg,$ylen) - { - $xlen = $xlen == 1 ? '' : ",$xlen"; - $ylen = $ylen == 1 ? '' : ",$ylen"; - - return "@@ -$xbeg$xlen +$ybeg$ylen @@"; - } -} - -/** -* A class to format a Diff as MOD Template instuctions. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new BBCodeDiffFormatter; -* echo $fmt->format($diff, $lines1); // Output MOD Actions. -*/ -class BBCodeDiffFormatter extends DiffFormatter -{ - function BBCodeDiffFormatter ($reverse = false, $context_lines = 3, $debug = false) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = $context_lines; - $this->context_prefix = ' '; - $this->deletes_prefix = '-'; - $this->adds_prefix = '+'; - $this->debug = $debug; - } - - function format ($diff, $from_lines) - { - $html = $this->_format($diff->edits, $from_lines); - - return $html; - } - - function skip_lines(&$order_array, &$ordering) - { - if (sizeof($order_array['find_c'])) - { - $text = implode('', $order_array['find_c']); - if ($text === "\n" || $text === "\t" || $text === '') - { - if (isset($order_array['first_find_c'][0]) && - is_array($order_array['first_find_c'][0]) && - trim(implode('', $order_array['first_find_c'][0])) != '' && - isset($order_array['replace'])) - { - $order_array['add'] = $order_array['replace']; - unset($order_array['replace']); - // this is actually an after add - } - else - { - return true; - } - } - } - - if (isset($order_array['add']) && sizeof($order_array['add'])) - { - $text = implode('', $order_array['add']); - if ($text === "\n" || $text === "\t" || $text === '') - { - return true; - } - } - - if (isset($order_array['replace']) && sizeof($order_array['replace'])) - { - $text = implode('', $order_array['replace']); - if ($text === "\n" || $text === "\t" || $text === '') - { - return true; - } - } - } - - function _emit_lines_bb($ybeg, &$ordering) - { - $html = ''; - - // Now adjust for bbcode display... - foreach ($ordering as $order_array) - { - // Skip useless empty lines... - if ($this->skip_lines($order_array, $ordering)) - { - continue; - } - - // Only include double-finds if the last find has very few code location indications... - if (isset($order_array['first_find_c']) && sizeof($order_array['first_find_c'])) - { - $text = implode('', $order_array['find_c']); - if ($text === "\n" || $text === "\t" || $text === '') - { - // no real find, use first_find_c if possible! - //var_dump($order_array); - if (is_array($order_array['first_find_c'][0])) - { - $order_array['find_c'] = $order_array['first_find_c'][0]; - } - else - { - if (isset($order_array['replace']) || isset($order_array['add']) || isset($order_array['delete'])) - { - echo "skipped an edit!\n"; - var_dump($order_array); - } - continue; - } - } - else - { - if (strlen(implode('', $order_array['find_c'])) < 50 && is_array($order_array['first_find_c'][0])) - { - $html .= "#\n#-----[ FIND ]---------------------------------------------\n# Around Line {$ybeg}\n"; - $html .= implode("", $order_array['first_find_c'][0]); - $html .= "\n"; - $ybeg += sizeof($order_array['first_find_c'][0]); - } - } - } - - // still here but nothing to do? what the heck? - if (!isset($order_array['replace']) && !isset($order_array['add']) && !isset($order_array['delete'])) - { - echo "skipped an edit!\n"; - var_dump($order_array); - continue; - } - - if (sizeof($order_array['find_c'])) - { - $html .= "#\n#-----[ FIND ]---------------------------------------------\n# Around Line {$ybeg}\n"; - $html .= implode("", $order_array['find_c']); - $html .= "\n"; - } - - if (isset($order_array['replace'])) - { - $html .= "#\n#-----[ REPLACE WITH ]---------------------------------------------\n#\n"; - $html .= implode("", $order_array['replace']); - $html .= "\n"; - } - - if (isset($order_array['add'])) - { - $html .= "#\n#-----[ AFTER, ADD ]---------------------------------------------\n#\n"; - $html .= implode("", $order_array['add']); - $html .= "\n"; - } - - // There is no DELETE. :o - // Let's try to adjust it then... - if (isset($order_array['delete'])) - { - $text = implode('', $order_array['delete']); - if ($text === "\n" || $text === "\t" || $text === '') - { - continue; - } - - $ybeg += sizeof($order_array['find_c']); - - $html .= "#\n#-----[ FIND ]---------------------------------------------\n# Around Line {$ybeg}\n"; - $html .= implode("", $order_array['delete']); - $html .= "\n"; - - $html .= "#\n#-----[ REPLACE WITH ]---------------------------------------------\n# Just remove/delete the lines (replacing with an empty line)\n"; - $html .= "\n"; - $html .= "\n"; - } - } - - return $html; - } - - function format_open($filename) - { - $html = ''; - $html .= "#\n#-----[ OPEN ]--------------------------------------------- \n#\n{$filename}\n\n"; - - return $html; - } - - function format_close($filename) - { - return ''; - } - - function _emit_diff ($xbeg, $xlen, $ybeg, $ylen, $hunks) - { - - // Go through the hunks to determine which method we are using (AFTER, ADD; REPLACE WITH or DELETE) - - // Remove the header... - if (sizeof($hunks) <= 2 && !isset($hunks[1]['a']) && !isset($hunks[1]['d'])) - { - $reorder = false; - $orig_hunks = $hunks; - - foreach ($hunks as $key => $hunk) - { - if (isset($hunk['a']) && isset($hunk['d'])) - { - /**/ if (sizeof($hunk['a']) == 1 && sizeof($hunk['d']) == 1) - { - if (preg_match('/\* @version \$Id:.+\$$/', $hunk['a'][0]) && preg_match('/\* @version \$Id:.+\$$/', $hunk['d'][0])) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - }/**/ - - // Compare the add and replace one... - $string_1 = rtrim(trim(implode('', $hunk['a']))); - $string_2 = rtrim(trim(implode('', $hunk['d']))); - - if (strcmp($string_1, $string_2) === 0) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - } - } - - if ($reorder) - { - // Now check if we have no more 'a' and 'd's - $hunks = array_merge($hunks, array()); - } - } - else - { - $reorder = false; - $orig_hunks = $hunks; - - foreach ($hunks as $key => $hunk) - { - if (isset($hunk['a']) && isset($hunk['d'])) - { - /**/ if (sizeof($hunk['a']) == 1 && sizeof($hunk['d']) == 1) - { - if (preg_match('/\* @version \$Id:.+\$$/', $hunk['a'][0]) && preg_match('/\* @version \$Id:.+\$$/', $hunk['d'][0])) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - }/**/ - - // Compare the add and replace one... - $string_1 = rtrim(trim(implode('', $hunk['a']))); - $string_2 = rtrim(trim(implode('', $hunk['d']))); - - if (strcmp($string_1, $string_2) === 0) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - } - } - - if ($reorder) - { - $hunks = array_merge($hunks, array()); - - if (sizeof($hunks) == 1 && sizeof($hunks[0]) == 1 && isset($hunks[0]['c'])) - { - return; - } - else - { - $hunks = $orig_hunks; - } - } - } - - if (sizeof($hunks) == 1 && sizeof($hunks[0]) == 1 && isset($hunks[0]['c'])) - { - return; - } - - $replace = false; - foreach ($hunks as $key => $hunk) - { - if (isset($hunk['d']) && isset($hunk['a'])) - { - $replace = true; - break; - } - } - - $ordering = array(); - $cur_pos = 0; - - // Replace-block - if ($replace) - { - foreach ($hunks as $hunk) - { - if (!isset($hunk['a']) && !isset($hunk['d'])) - { - continue; - } - - if (!empty($hunk['c'])) - { - if (!isset($ordering[$cur_pos]['find_c'])) - { - $ordering[$cur_pos]['find_c'] = $hunk['c']; - } - else - { - $ordering[$cur_pos]['end_c'] = $hunk['c']; - } - } - - // Make sure we begin fresh... - if (!isset($ordering[$cur_pos]['replace'])) - { - $ordering[$cur_pos]['first_find_c'][] = $ordering[$cur_pos]['find_c']; - $ordering[$cur_pos]['find_c'] = array(); - $ordering[$cur_pos]['replace'] = array(); - } - - // Add the middle part if one exist... - if (isset($ordering[$cur_pos]['end_c'])) - { - $ordering[$cur_pos]['find_c'] = array_merge($ordering[$cur_pos]['find_c'], $ordering[$cur_pos]['end_c']); - $ordering[$cur_pos]['replace'] = array_merge($ordering[$cur_pos]['replace'], $ordering[$cur_pos]['end_c']); - unset($ordering[$cur_pos]['end_c']); - } - - if (isset($hunk['d'])) - { - $ordering[$cur_pos]['find_c'] = array_merge($ordering[$cur_pos]['find_c'], $hunk['d']); - } - - if (isset($hunk['a'])) - { - $ordering[$cur_pos]['replace'] = array_merge($ordering[$cur_pos]['replace'], $hunk['a']); - } - } - } - else - { - foreach ($hunks as $hunk) - { - if (!empty($hunk['c'])) - { - if (!isset($ordering[$cur_pos]['find_c'])) - { - $ordering[$cur_pos]['find_c'] = $hunk['c']; - } - else - { - $ordering[$cur_pos]['end_c'] = $hunk['c']; - } - } - - if (!empty($hunk['a'])) - { - if (isset($ordering[$cur_pos]['delete'])) - { - // If ordering is set with an delete entry, we will actually begin a new ordering array (to seperate delete from add) - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['add'] = $hunk['a']; - } - else - { - if (isset($ordering[$cur_pos]['add'])) - { - // Now, we really need to be quite careful here... - if (isset($ordering[$cur_pos]['end_c']) && isset($hunk['c']) && isset($hunk['a']) && sizeof($hunk) == 2) - { - // There is a new find/add entry we did not catch... let's try to add a new entry then... but first check the hunk[a] contents... - $text = trim(implode("\n", $hunk['c'])); - if ($text == "\n" || !$text) - { - $ordering[$cur_pos]['add'] = array_merge($ordering[$cur_pos]['add'], array("\n"), $hunk['a']); - } - else if (sizeof($hunk['c']) > 2 || strlen(implode('', $hunk['c'])) > 20) - { - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['add'] = $hunk['a']; - } - else - { - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['add'] = $hunk['a']; -/* echo 'FIND STATEMENT TOO TINY'; - echo ";".rawurlencode($text).";"; - var_dump($hunk); - exit;*/ - } - } - else - { - echo 'UNCATCHED ENTRY'; - var_dump($hunks); - exit; - } - } - else - { - $ordering[$cur_pos]['add'] = $hunk['a']; - } - } - } - else if (!empty($hunk['d'])) - { - if (isset($ordering[$cur_pos]['add'])) - { - // If ordering is set with an add entry, we will actually begin a new ordering array (to seperate delete from add) - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['delete'] = $hunk['d']; - } - else - { - $ordering[$cur_pos]['delete'] = $hunk['d']; - } - } - } - } - - $html = ''; - - return $this->_emit_lines_bb($ybeg, $ordering); - } - - function _diff_header($xbeg, $xlen, $ybeg, $ylen) - { - } -} - - -/** -* A class to format a Diff as MOD Template instuctions. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new BBCodeDiffFormatter; -* echo $fmt->format($diff, $lines1); // Output MOD Actions. -*/ -class MODXDiffFormatter extends BBCodeDiffFormatter -{ - function MODXDiffFormatter ($reverse = false, $context_lines = 3, $debug = false) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = $context_lines; - $this->context_prefix = ' '; - $this->deletes_prefix = '-'; - $this->adds_prefix = '+'; - $this->debug = $debug; - } - - function _emit_lines_bb($ybeg, &$ordering) - { - $html = ''; - - // Now adjust for bbcode display... - foreach ($ordering as $order_array) - { - // Skip useless empty lines... - if ($this->skip_lines($order_array, $ordering)) - { - continue; - } - - // Only include double-finds if the last find has very few code location indications... - if (sizeof($order_array['first_find_c'])) - { - $text = implode('', $order_array['find_c']); - if ($text === "\n" || $text === "\t" || $text === '') - { - continue; - } - - if (strlen(implode('', $order_array['find_c'])) < 50) - { - if (substr($html, -8) !== '</find>' . "\n") - { - $html .= ' <edit>' . "\n"; - } - - $html .= ' <comment lang="en">Around Line ' . $ybeg . '</comment>' . "\n"; - $html .= ' <find>' . htmlspecialchars(implode('', $order_array['first_find_c'][0])) . '</find>' . "\n"; - $ybeg += sizeof($order_array['first_find_c'][0]); - } - } - - if (sizeof($order_array['find_c'])) - { - if (substr($html, -8) !== '</find>' . "\n") - { - $html .= ' <edit>' . "\n"; - } - -// $html .= ' <edit>' . "\n"; - $html .= ' <comment lang="en">Around Line ' . $ybeg . '</comment>' . "\n"; - $html .= ' <find>' . htmlspecialchars(implode('', $order_array['find_c'])) . '</find>' . "\n"; - } - - if (isset($order_array['replace'])) - { - $html .= ' <action type="replace-with">' . htmlspecialchars(implode('', $order_array['replace'])) . '</action>' . "\n"; - $html .= ' </edit>' . "\n"; - } - - if (isset($order_array['add'])) - { - $html .= ' <action type="after-add">' . htmlspecialchars(implode('', $order_array['add'])) . '</action>' . "\n"; - $html .= ' </edit>' . "\n"; - } - - // There is no DELETE. :o - // Let's try to adjust it then... - if (isset($order_array['delete'])) - { - $text = implode('', $order_array['delete']); - if ($text === "\n" || $text === "\t" || $text === '') - { - continue; - } - - $ybeg += sizeof($order_array['find_c']); - - if (substr($html, -8) !== '</find>' . "\n") - { - $html .= ' <edit>' . "\n"; - } - $html .= ' <comment lang="en">Around Line ' . $ybeg . ' / Just remove/delete the lines (replacing with an empty line)</comment>' . "\n"; - $html .= ' <find>' . htmlspecialchars(implode('', $order_array['delete'])) . '</find>' . "\n"; - $html .= ' <action type="replace-with"></action>' . "\n"; - $html .= ' </edit>'; - } - } - - return $html; - } - - function format_open($filename) - { - return '<open src="' . $filename . '">' . "\n"; - } - - function format_close($filename) - { - return '</open>' . "\n"; - } - - function _diff_header($xbeg, $xlen, $ybeg, $ylen) - { - } -} diff --git a/git-tools/commit-msg-hook-range.sh b/git-tools/commit-msg-hook-range.sh new file mode 100755 index 0000000000..2b408c3e79 --- /dev/null +++ b/git-tools/commit-msg-hook-range.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# @copyright (c) 2014 phpBB Group +# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +# +# Calls the git commit-msg hook on all non-merge commits in a given commit range. +# + +if [ "$#" -ne 1 ]; +then + echo "Expected one argument (commit range, e.g. phpbb/develop..ticket/12345)." + exit +fi + +DIR=$(dirname "$0") +COMMIT_RANGE="$1" +COMMIT_MSG_HOOK_PATH="$DIR/hooks/commit-msg" +COMMIT_MSG_HOOK_FATAL=$(git config --bool phpbb.hooks.commit-msg.fatal 2> /dev/null) +git config phpbb.hooks.commit-msg.fatal true + +EXIT_STATUS=0 +for COMMIT_HASH in $(git rev-list --no-merges "$COMMIT_RANGE") +do + echo "Inspecting commit message of commit $COMMIT_HASH" + + # The git commit-msg hook takes a path to a file containing a commit + # message. So we have to extract the commit message into a file first, + # which then also needs to be deleted after our work is done. + COMMIT_MESSAGE_PATH="$DIR/commit_msg.$COMMIT_HASH" + git log -n 1 --pretty=format:%B "$COMMIT_HASH" > "$COMMIT_MESSAGE_PATH" + + # Invoke hook on commit message file. + "$COMMIT_MSG_HOOK_PATH" "$COMMIT_MESSAGE_PATH" + + # If any commit message hook complains with a non-zero exit status, we + # will send a non-zero exit status upstream. + if [ $? -ne 0 ] + then + EXIT_STATUS=1 + fi + + rm "$COMMIT_MESSAGE_PATH" +done + +# Restore phpbb.hooks.commit-msg.fatal config +if [ -n "$COMMIT_MSG_HOOK_FATAL" ] +then + git config phpbb.hooks.commit-msg.fatal "$COMMIT_MSG_HOOK_FATAL" +fi + +exit $EXIT_STATUS diff --git a/phpBB/adm/style/editor.js b/phpBB/adm/style/editor.js index 217aa699e2..cad01aa9f2 100644 --- a/phpBB/adm/style/editor.js +++ b/phpBB/adm/style/editor.js @@ -292,7 +292,7 @@ function mozWrap(txtarea, open, close) */ function storeCaret(textEl) { - if (textEl.createTextRange) + if (textEl.createTextRange && document.selection) { textEl.caretPos = document.selection.createRange().duplicate(); } diff --git a/phpBB/docs/AUTHORS b/phpBB/docs/AUTHORS index 5995bd2ab4..465c4de397 100644 --- a/phpBB/docs/AUTHORS +++ b/phpBB/docs/AUTHORS @@ -23,10 +23,11 @@ involved in phpBB. phpBB Lead Developer: naderman (Nils Adermann) phpBB Developers: bantu (Andreas Fischer) - EXreaction (Nathan Guse) dhruv.goel92 (Dhruv Goel) + EXreaction (Nathan Guse) imkingdavid (David King) nickvergessen (Joas Schilling) + prototech (Cesar Gallegos) Contributions by: leviatan21 (Gabriel Vazquez) Raimon (Raimon Meuldijk) diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index f63ff18cbe..e394b1ffa0 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -477,7 +477,7 @@ class phpbb_db_tools // here lies an array, filled with information compiled on the column's data $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - if (isset($prepared_column['auto_increment']) && strlen($column_name) > 26) // "${column_name}_gen" + if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen" { trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR); } diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index d0e7c8cfc8..bb6913a572 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -436,21 +436,21 @@ class p_master if ($this->active_module === false) { - trigger_error('Module not accessible', E_USER_ERROR); + trigger_error('MODULE_NOT_ACCESS', E_USER_ERROR); } if (!class_exists("{$this->p_class}_$this->p_name")) { if (!file_exists("$module_path/{$this->p_class}_$this->p_name.$phpEx")) { - trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR); + trigger_error($user->lang('MODULE_NOT_FIND', "$module_path/{$this->p_class}_$this->p_name.$phpEx"), E_USER_ERROR); } include("$module_path/{$this->p_class}_$this->p_name.$phpEx"); if (!class_exists("{$this->p_class}_$this->p_name")) { - trigger_error("Module file $module_path/{$this->p_class}_$this->p_name.$phpEx does not contain correct class [{$this->p_class}_$this->p_name]", E_USER_ERROR); + trigger_error($user->lang('MODULE_FILE_RIGHT_CLASS', "$module_path/{$this->p_class}_$this->p_name.$phpEx", "{$this->p_class}_$this->p_name"), E_USER_ERROR); } if (!empty($mode)) diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index 8573533c2c..a2c0656ca4 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -532,7 +532,7 @@ class custom_profile switch ($this->profile_types[$field_type]) { case 'int': - if ($value === '' && !$ident_ary['data']['field_show_novalue']) + if (($value === '' || $value === null) && !$ident_ary['data']['field_show_novalue']) { return NULL; } diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index dc961f3c8a..29c5a72874 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -231,7 +231,12 @@ class fulltext_native extends search_backend } $db->sql_freeresult($result); } - unset($exact_words); + + // Handle +, - without preceeding whitespace character + $match = array('#(\S)\+#', '#(\S)-#'); + $replace = array('$1 +', '$1 +'); + + $keywords = preg_replace($match, $replace, $keywords); // now analyse the search query, first split it using the spaces $query = explode(' ', $keywords); @@ -357,39 +362,21 @@ class fulltext_native extends search_backend $this->{$mode . '_ids'}[] = $words[$word]; } } - // throw an error if we shall not ignore unexistant words - else if (!$ignore_no_id) + else { if (!isset($common_ids[$word])) { $len = utf8_strlen($word); - if ($len >= $this->word_length['min'] && $len <= $this->word_length['max']) - { - trigger_error(sprintf($user->lang['WORD_IN_NO_POST'], $word)); - } - else + if ($len < $this->word_length['min'] || $len > $this->word_length['max']) { $this->common_words[] = $word; } } } - else - { - $len = utf8_strlen($word); - if ($len < $this->word_length['min'] || $len > $this->word_length['max']) - { - $this->common_words[] = $word; - } - } - } - - // we can't search for negatives only - if (!sizeof($this->must_contain_ids)) - { - return false; } - if (!empty($this->search_query)) + // Return true if all words are not common words + if (sizeof($exact_words) - sizeof($this->common_words) > 0) { return true; } @@ -428,6 +415,12 @@ class fulltext_native extends search_backend return false; } + // we can't search for negatives only + if (empty($this->must_contain_ids)) + { + return false; + } + $must_contain_ids = $this->must_contain_ids; $must_not_contain_ids = $this->must_not_contain_ids; $must_exclude_one_ids = $this->must_exclude_one_ids; diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index ccd12fcb6a..f9a40c2bc7 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -44,7 +44,7 @@ $lang = array_merge($lang, array( 'DEFAULT_LANGUAGE' => 'Default language', 'DEFAULT_STYLE' => 'Default style', 'DISABLE_BOARD' => 'Disable board', - 'DISABLE_BOARD_EXPLAIN' => 'This will make the board unavailable to users. You can also enter a short (255 character) message to display if you wish.', + 'DISABLE_BOARD_EXPLAIN' => 'This will make the board unavailable to users who are neither administrators nor moderators. You can also enter a short (255 character) message to display if you wish.', 'OVERRIDE_STYLE' => 'Override user style', 'OVERRIDE_STYLE_EXPLAIN' => 'Replaces user’s style with the default.', 'SITE_DESC' => 'Site description', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index f37f6d3b30..663369b8fa 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -341,6 +341,9 @@ $lang = array_merge($lang, array( 'MODERATE' => 'Moderate', 'MODERATOR' => 'Moderator', 'MODERATORS' => 'Moderators', + 'MODULE_NOT_ACCESS' => 'Module not accessible', + 'MODULE_NOT_FIND' => 'Cannot find module %s', + 'MODULE_FILE_RIGHT_CLASS' => 'Module file %s does not contain correct class [%s]', 'MONTH' => 'Month', 'MOVE' => 'Move', 'MSNM' => 'MSNM/WLM', diff --git a/phpBB/search.php b/phpBB/search.php index ad9c371f63..0f13dbbfa0 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -540,12 +540,6 @@ if ($keywords || $author || $author_id || $search_id || $submit) $total_match_count = $search->author_search($show_results, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page); } - // For some searches we need to print out the "no results" page directly to allow re-sorting/refining the search options. - if (!sizeof($id_ary) && !$search_id) - { - trigger_error('NO_SEARCH_RESULTS'); - } - $sql_where = ''; if (sizeof($id_ary)) diff --git a/phpBB/styles/prosilver/template/editor.js b/phpBB/styles/prosilver/template/editor.js index c16b0ef703..42be70be92 100644 --- a/phpBB/styles/prosilver/template/editor.js +++ b/phpBB/styles/prosilver/template/editor.js @@ -347,7 +347,7 @@ function mozWrap(txtarea, open, close) */ function storeCaret(textEl) { - if (textEl.createTextRange) + if (textEl.createTextRange && document.selection) { textEl.caretPos = document.selection.createRange().duplicate(); } diff --git a/phpBB/styles/prosilver/template/ucp_groups_manage.html b/phpBB/styles/prosilver/template/ucp_groups_manage.html index c90461312e..53d2dfffb3 100644 --- a/phpBB/styles/prosilver/template/ucp_groups_manage.html +++ b/phpBB/styles/prosilver/template/ucp_groups_manage.html @@ -54,7 +54,7 @@ <fieldset> <dl> <dt><label for="group_colour">{L_GROUP_COLOR}:</label><br /><span>{L_GROUP_COLOR_EXPLAIN}</span></dt> - <dd><input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" class="inputbox narrow" /> <span style="background-color: {GROUP_COLOUR};"> </span> [ <a href="{U_SWATCH}" onclick="popup(this.href, 636, 150, '_swatch'); return false;">{L_COLOUR_SWATCH}</a> ]</dd> + <dd><input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" class="inputbox narrow" /> <span style="background-color: #{GROUP_COLOUR};"> </span> [ <a href="{U_SWATCH}" onclick="popup(this.href, 636, 150, '_swatch'); return false;">{L_COLOUR_SWATCH}</a> ]</dd> </dl> <dl> <dt><label for="group_rank">{L_GROUP_RANK}:</label></dt> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html index 67e14defc3..91dd4606c8 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html @@ -8,8 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="keywords" content="" /> -<meta name="description" content="" /> <meta name="robots" content="noindex" /> {META} <title>{SITENAME} • {PAGE_TITLE}</title> diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html index 39d2d76394..168305a6a4 100644 --- a/phpBB/styles/prosilver/template/viewtopic_print.html +++ b/phpBB/styles/prosilver/template/viewtopic_print.html @@ -8,8 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="keywords" content="" /> -<meta name="description" content="" /> <meta name="robots" content="noindex" /> {META} <title>{SITENAME} • {PAGE_TITLE}</title> diff --git a/phpBB/styles/subsilver2/template/editor.js b/phpBB/styles/subsilver2/template/editor.js index 151cf53ff1..103a271a71 100644 --- a/phpBB/styles/subsilver2/template/editor.js +++ b/phpBB/styles/subsilver2/template/editor.js @@ -351,7 +351,7 @@ function mozWrap(txtarea, open, close) */ function storeCaret(textEl) { - if (textEl.createTextRange) + if (textEl.createTextRange && document.selection) { textEl.caretPos = document.selection.createRange().duplicate(); } diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html index cd55c16a50..085e26ecd2 100644 --- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html @@ -4,6 +4,7 @@ <meta http-equiv="Content-Type" content="text/html; charset={S_CONTENT_ENCODING}"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Language" content="{S_USER_LANG}"> +<meta name="robots" content="noindex" /> <title>{SITENAME} :: {PAGE_TITLE}</title> <style type="text/css"> diff --git a/phpBB/styles/subsilver2/template/viewtopic_print.html b/phpBB/styles/subsilver2/template/viewtopic_print.html index 1ca1eccc99..47b5bdb28e 100644 --- a/phpBB/styles/subsilver2/template/viewtopic_print.html +++ b/phpBB/styles/subsilver2/template/viewtopic_print.html @@ -4,6 +4,7 @@ <meta http-equiv="Content-Type" content="text/html; charset={S_CONTENT_ENCODING}"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Language" content="{S_USER_LANG}"> +<meta name="robots" content="noindex" /> <title>{SITENAME} :: {PAGE_TITLE}</title> <style type="text/css"> diff --git a/tests/lint_test.php b/tests/lint_test.php index eba117839b..b0149063bd 100644 --- a/tests/lint_test.php +++ b/tests/lint_test.php @@ -9,17 +9,30 @@ class phpbb_lint_test extends phpbb_test_case { + static protected $php_binary; static protected $exclude; static public function setUpBeforeClass() { + // Try to use PHP_BINARY constant if available so lint tests are run + // using the same php binary as phpunit. If not available (pre PHP + // 5.4), assume binary is called 'php' and is in PATH. + self::$php_binary = defined('PHP_BINARY') ? escapeshellcmd(PHP_BINARY) : 'php'; + $output = array(); $status = 1; - exec('(php -v) 2>&1', $output, $status); + exec(sprintf('(%s --version) 2>&1', self::$php_binary), $output, $status); if ($status) { $output = implode("\n", $output); - self::markTestSkipped("php is not in PATH or broken: $output"); + if (self::$php_binary === 'php') + { + self::markTestSkipped(sprintf('php is not in PATH or broken. Output: %s', $output)); + } + else + { + self::markTestSkipped(sprintf('Could not run PHP_BINARY %s. Output: %s', self::$php_binary, $output)); + } } self::$exclude = array( @@ -65,13 +78,12 @@ class phpbb_lint_test extends phpbb_test_case } else if (substr($filename, strlen($filename)-4) == '.php') { - // assume php binary is called php and it is in PATH - $cmd = '(php -l ' . escapeshellarg($path) . ') 2>&1'; + $cmd = sprintf('(%s -l %s) 2>&1', self::$php_binary, escapeshellarg($path)); $output = array(); $status = 1; exec($cmd, $output, $status); $output = implode("\n", $output); - $this->assertEquals(0, $status, "php -l failed for $path:\n$output"); + $this->assertEquals(0, $status, "PHP lint failed for $path:\n$output"); } } } diff --git a/tests/profile/get_profile_value_test.php b/tests/profile/get_profile_value_test.php new file mode 100644 index 0000000000..a5f37a85ce --- /dev/null +++ b/tests/profile/get_profile_value_test.php @@ -0,0 +1,42 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_profile_fields.php'; + +class phpbb_profile_get_profile_value_test extends phpbb_test_case +{ + static public function get_profile_value_int_data() + { + return array( + array(FIELD_INT, '10', true, 10), + array(FIELD_INT, '0', true, 0), + array(FIELD_INT, '', true, 0), + array(FIELD_INT, null, true, 0), + array(FIELD_INT, '10', false, 10), + array(FIELD_INT, '0', false, 0), + array(FIELD_INT, '', false, null), + array(FIELD_INT, null, false, null), + ); + } + + /** + * @dataProvider get_profile_value_int_data + */ + public function test_get_profile_value_int($type, $value, $show_novalue, $expected) + { + $cp = new custom_profile; + $this->assertSame($expected, $cp->get_profile_value(array( + 'value' => $value, + 'data' => array( + 'field_type' => $type, + 'field_show_novalue' => $show_novalue, + ), + ))); + } +} |