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

// make absolute or relative to phpBB /
define('PHPBB_ROOT_PATH', '../');
define('IN_PHPBB', true);


function confirm($message = 'Are you sure? ', $options = array('y', 'n'), $default ='n')
{
   // first $options means true, any other false

   echo $message, ' (';
   $first = true;
   foreach ($options as $option) {
      // mark default
      if ($option == $default) {
         $option = strtoupper($option);
      }
      if ($first) {
         echo $option;
         $first = false;
      } else {
         echo '/', $option;
      }
   }
   echo '): ';

   $handle = fopen("php://stdin", 'r');
   $line = trim(fgetc($handle));
   fclose($handle);


   if ($line == '') {
      // enter
      $line = $default;
   }

   if ($line == $options[0]) {
      $result = true;
   } else {
      $result = false;
   }

   return $result;
}



function deleteDirectory($dir, $excludes = array())
{
   if (!file_exists($dir)) {
      return false;
   }
   $dir = rtrim($dir, '/') . '/';
   static $skip = false;

   $entries = glob($dir . '{,.}[!.,!..]*', GLOB_MARK | GLOB_BRACE);

   foreach($entries as $entry) {
      if (!in_array(basename($entry), $excludes)) {
         if (is_dir($entry)) {
            deleteDirectory($entry);
         } else {
            unlink($entry);
         }
      } else {
         $skip = true;
      }
   }
   if ($skip == false) {
      rmdir($dir);
   }
}



function copyDirectory($source, $target)
{
   if (!file_exists($source)) {
      die("missing source: $source");
   }

   if (is_file($source)) {
      if (copy($source, $target)) {
         return true;
      } else {
         return false;
      }
   }

   if (is_dir($source)) {
      if (!file_exists($target)) {
         mkdir($target);
      }
      $source = rtrim($source, '/') . '/';
      $target = rtrim($target, '/') . '/';
      $dir = new DirectoryIterator($source);

      foreach ($dir as $entry) {
         if (!$entry->isDot()) {
            copyDirectory("$source$entry", "$target$entry");
         }
      }
   }

   // ignore links, not part of phpBB arch
}


$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);

if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    echo 'This script is intended for unixoid installations.';
    exit(1);
}


$fileowner = fileowner($phpbb_root_path);
$filegroup = filegroup($phpbb_root_path);
$fileownerName = posix_getpwuid($fileowner)['name'];
$filegroupName = posix_getgrgid($filegroup)['name'];


if (!empty($argv[1])) {
   switch ($argv[1]) {
      case '--prepare':
         // handle version stuff
         $sql = "SELECT config_value FROM ${table_prefix}config WHERE config_name = 'version'";
         $result = $db->sql_query($sql);
         $row = $db->sql_fetchrow($result);
         $installedVersion = $row['config_value'];
         print("Installed version: $installedVersion" . PHP_EOL);

         // phpBB has major, minor and maintenance version scheme
         list($major, $minor, $patch) = explode('.', $installedVersion);
         if ((intval($major) != 3) || (intval($minor) != 2)) {
            echo "This script only supports phpBB 3.2 branch.", PHP_EOL;
            exit(1);
         }


         // ok, start update
         $now = date('d.m.Y H:i');
         $disableMsg = "Softwareupdate am $now, das Bord ist kurzzeitig nicht erreichbar.";
         $sql = "UPDATE ${table_prefix}config SET config_value = '$disableMsg' WHERE config_name = 'board_disable_msg'";
         $result = $db->sql_query($sql);
         echo "Disable Message set …", PHP_EOL;

         $sql = "UPDATE ${table_prefix}config SET config_value = '1' WHERE config_name = 'board_disable'";
         $result = $db->sql_query($sql);
         echo "Board disabled …", PHP_EOL;

         // clear cache
         $data_global_cache = $phpbb_root_path . '/cache/data_global.' . $phpEx;

         if (file_exists($data_global_cache)) {
            unlink($data_global_cache);
            echo "Cache cleared …";
         }


         // http://version.phpbb.com/phpbb/versions.json
         $json = file_get_contents('http://version.phpbb.com/phpbb/versions.json');
         $versions = json_decode($json);
         $currentVersion = $versions->{'stable'}->{'3.2'}->{'current'};
         print("Current version: $currentVersion" . PHP_EOL);

         // check for existing update
         if (!file_exists('dist')) {
            echo "'dist' folder is missing, create a new one …'";
            mkdir ('dist');
         }
         $currentFile = "phpBB-$currentVersion-deutsch.tar.bz2";
         $filePath = "http://downloads.phpbb.de/pakete/deutsch/3.2/$currentVersion/$currentFile";
         $target = "dist/$currentFile";

         if (!file_exists($target)) {
            print("Downloading $currentFile");
            $phpBBtbz = file_get_contents($filePath);
            file_put_contents($target, $phpBBtbz);
         } else {
            print("File exists: $currentFile" . PHP_EOL);
            if (!confirm('Use this copy and continue?')) {
               echo "Aborted due to user request.", PHP_EOL;
               exit(1);
            }

         }
         $data  = new PharData($target);
         try {
            unset($data['phpBB3/config.php']);
            unset($data['phpBB3/.htaccess']);
         } catch (Exception $e) {
            echo 'error: ', $e;
         }

         // check for enabled extensions
         $sql = "SELECT ext_name FROM ${table_prefix}ext WHERE ext_active = '1'";
         $result = $db->sql_query($sql);
         $rows = $db->sql_fetchrowset($result);
         if (count($rows) > 0) {
            $rows = json_encode($rows);

            // safe enabled extensions
            $ofile = fopen('extensions.txt', 'w');
            fputs($ofile, $rows);
            fclose($ofile);

            // disable all extensions
            $sql = "UPDATE ${table_prefix}ext SET ext_active = '0' WHERE ext_active = '1'";
            $result = $db->sql_query($sql);
         }

         // disable all styles but prosilver
         $sql = "UPDATE ${table_prefix}styles SET style_active = '0' WHERE NOT style_name = 'prosilver'";
         $result = $db->sql_query($sql);

         // remove all old files
         $excludes = array(
            'config.php',
            '.htaccess',
            '.htpasswd',
            'images',
            'files',
            'ext',
            'styles',
            'store',
            'updates',
            'mobiquo');
         // this will fuck up nearly all modified boards, leave the files alone by default
         //         deleteDirectory($phpbb_root_path, $excludes);


         try {
            // $data->extractTo($phpbb_root_path, 'phpBB3');
            // does not work due to php bug:
            // https://bugs.php.net/bug.php?id=54289
            $data->extractTo($phpbb_root_path, null, true);

            $fromDir = $phpbb_root_path . 'phpBB3/';
            $toDir = $phpbb_root_path;

            copyDirectory($fromDir, $toDir);
            deleteDirectory($fromDir);

         } catch (Exception $e) {
            print("Error while extracting $data: $e");
            exit(1);
         }
         echo 'Moved the update in place.', PHP_EOL;

         echo 'Check fileowner', PHP_EOL;
         print("You might need to perform 'chown -R $fileownerName:$filegroupName $phpbb_root_path'" . PHP_EOL);

         echo 'prepare config.yml.', PHP_EOL;
         $oFile = fopen($phpbb_root_path . '/install/config.yml', 'w');
         fputs($oFile, 'updater:' . PHP_EOL . "        type: db_only" . PHP_EOL);
         fclose($oFile);
         echo "Now head over to ${phpbb_root_path}install and execute 'php phpbbcli.php update config.yml'", PHP_EOL;
         echo "After, return here and finish the update by excuting php $argv[0] --finish", PHP_EOL;
         exit(0);
      break;

      case "--finish":
         if (confirm('Remove the install directory?')) {
            deleteDirectory($phpbb_root_path . 'install');
         }

         $sql = "UPDATE ${table_prefix}config SET config_value = '0' WHERE config_name = 'board_disable'";
         $result = $db->sql_query($sql);

         echo "Board reenabled …", PHP_EOL;

         // clear cache
         $data_global_cache = $phpbb_root_path . '/cache/production/data_global.' . $phpEx;

         if (file_exists($data_global_cache)) {
            unlink($data_global_cache);
            echo "Cache cleared …", PHP_EOL;
         }
         echo "Your board should now be up and running, you might want to reeanble the extensions using php $argv[0] --reenable-extensions", PHP_EOL;
         exit(0);
      break;
      case "--reenable-extensions":
         $extensionsFile = 'extensions.txt';

         if (file_exists($extensionsFile)) {
            $iFile = fopen($extensionsFile, 'r');
            $extensions = json_decode(fgets($iFile), true);

            echo 'Enable extensions: ';

            foreach($extensions as $extension) {
               $ext = $extension['ext_name'];
               // disable all extensions
               $sql = "UPDATE ${table_prefix}ext SET ext_active = '1' WHERE ext_name = '$ext'";
               $result = $db->sql_query($sql);
               echo '.';
            }
            echo 'done.', PHP_EOL;

            // clear cache
            $data_ext_cache = $phpbb_root_path . '/cache/production/data_ext.' . $phpEx;

            if (file_exists($data_ext_cache)) {
               unlink($data_ext_cache);
               echo "Cache cleared …", PHP_EOL;
            }

         } else {
            echo 'There are no saved extension information available.', PHP_EOL;
         }
         exit(0);
      break;

      default:
         echo "unknow option $argv[1]", PHP_EOL;
      exit(1);
   }
} else {
   echo "$argv[0]: missing parameter", PHP_EOL;
   echo 'Usage:', PHP_EOL;
   echo 'To perfom an update, you need two steps. Fist prepare the board for the update:', PHP_EOL;
   echo "php $argv[0] --prepare", PHP_EOL;
   echo 'Then perform the DB update with the CLI tool from phpBB, after:', PHP_EOL;
   echo "php $argv[0] --finish", PHP_EOL;
   echo "Additional steps:", PHP_EOL;
   echo "php $argv[0] --reenable-extensions", PHP_EOL;
//   echo "php $argv[0] --reenable-styles", PHP_EOL;
//   really?
   exit(0);
}