#!/usr/bin/env php
<?php

/**
 * In the past, Civi bundled a hacked copy of PHPUnit used like:
 *
 *   cd tools
 *   ./scripts/phpunit Some_Class_NameTest
 *
 * This script is an adapter for backwards compatibility.
 */

$argFilters = [];

if (PHP_SAPI !== 'cli') {
  die("phpunit can only be run from command line.");
}
if (version_compare(PHP_VERSION, '7.2', '>=')) {
  $phpunit = findCommand('phpunit8');
  $argFilters[] = function ($argv) {
    $pos = array_search('--tap', $argv);
    if ($pos !== FALSE) {
      array_splice($argv, $pos, 1, ['--printer', '\Civi\Test\TAP']);
    }
    return $argv;
  };
}
elseif (version_compare(PHP_VERSION, '7.1', '>=')) {
  $phpunit = findCommand('phpunit7');
  $argFilters[] = function ($argv) {
    $pos = array_search('--tap', $argv);
    if ($pos !== FALSE) {
      array_splice($argv, $pos, 1, ['--printer', '\Civi\Test\TAP']);
    }
    return $argv;
  };
}
elseif (version_compare(PHP_VERSION, '7.0', '>=')) {
  $phpunit = findCommand('phpunit6');
  $argFilters[] = function ($argv) {
    $pos = array_search('--tap', $argv);
    if ($pos !== FALSE) {
      array_splice($argv, $pos, 1, ['--printer', '\Civi\Test\TAP']);
    }
    return $argv;
  };
}
elseif (version_compare(PHP_VERSION, '5.6', '>=')) {
  $phpunit = findCommand('phpunit5');
}
else {
  $phpunit = findCommand('phpunit4');
}
if (!$phpunit) {
  $phpunit = findCommand('phpunit');
}
if (!$phpunit) {
  echo "Plesae ensure that:\n";
  echo " * PHPUnit is installed.\n";
  echo " * The extensions for dbunit and selenium are installed.\n" ;
  echo " * The command \"phpunit\" is in the PATH.\n";
  echo "See also: https://github.com/civicrm/civicrm-buildkit/\n";
  exit(127);
}

chdir(dirname(dirname(__DIR__))); // civicrm-core root dir

array_shift($argv);

// Convert class names to file names
$CIVICRM_UF = 'UnitTests';
foreach ($argv as $k => $v) {
  if (preg_match('/^(CRM_|api_v3_|api_v4_|EnvTest|WebTest_|E2E_)/', $v)) {
    $argv[$k] = 'tests/phpunit/' . strtr($v, '_', '/') . '.php';
  }
  elseif (preg_match('/^Civi\\\\/', $v)) {
    $argv[$k] = 'tests/phpunit/' . strtr($v, '\\', '/') . '.php';
  }

  if (preg_match('/^(WebTest|E2E)/', $v)) {
    $CIVICRM_UF='';
  }
}
putenv("CIVICRM_UF=$CIVICRM_UF");

// Transition: Make sure we use phpunit code from PATH, not
// civicrm-packages.  This will be unnecessary once civicrm-packages is
// updated.
if (is_dir('packages/PHPUnit/')) {
  if (!rename('packages/PHPUnit', 'packages/PHPUnit.bak')) {
    echo "Failed to move aside stale copy of PHPUnit.\n";
    exit(1);
  }
}

foreach ($argFilters as $filter) {
  $argv = $filter($argv);
}

$cmd =
  findPhp() // In case this system has multiple copies of PHP, use the active/preferred one.
  // . ' -ddisplay_errors=1'
  . ' '
  . escapeshellarg($phpunit)
  . ' '
  . implode(' ', array_map('escapeshellarg', $argv));
passthru($cmd);

function findPhp() {
  // The autodetect behavior here is a potential point of contention. These two cases are hard to reconcile:
  // 1. `php` is actually a wrapper script which delegates to another PHP binary and
  //    passes options (such as INI's and PECL extensions). Subprocesses should use the wrapper script.
  //    Examples: bitnami, bknix
  // 2. There are multiple PHP binaries (eg `php55`, `php70`). Subprocesses should use
  //    the final executable (regardless of its name).
  //    Example: using MAMP and adding 'ln -s /Application/MAMP/.../php7.1.2/bin/php ~/bin/php71`
  // Since the test infra uses a wrapper script like (1), we use autodetect logic that works there.
  // If you're in situation (2), then set an env-var or just skip on using `tools/scripts/phpunit`.
  if (getenv('PHP')) {
    return getenv('PHP');
  }
  else {
    return 'php';
  }
}

function findCommand($name) {
  $paths = explode(PATH_SEPARATOR, getenv('PATH'));
  foreach ($paths as $path) {
    if (file_exists("$path/$name")) {
      return "$path/$name";
    }
  }
  return NULL;
}
