#!/usr/bin/php
<?PHP
#
#   FILE:  cwis (CWIS command line utility)
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2016 Edward Almasy and Internet Scout Research Group
#   http://scout.wisc.edu/cwis/
#

$GLOBALS["CCLUVersion"] = "1.0.1";
$GLOBALS["CCLURequiredCwisVersion"] = "3.9.1";

/**
* Print usage information.
*/
function PrintHelp()
{
    global $CCLUVersion;
    print <<<EOT
CWIS Command Line Utility $CCLUVersion
Usage: cwis command [arguments]
Commands:
  clearcache    clear page/object/template cache
  defaultui     set default user interface
  lschemas      list metadata schemas
  pdisable      disable plugin
  penable       enable plugin
  tlist         list queued/running/orphaned tasks
  upriv         add/remove/list user privileges
Enter a command with no arguments for help on that specific command.

EOT;
}

# check to make sure we are running from the command line
if (php_sapi_name() != "cli")
{
    print "Must be running from the command line.\n";
    exit(1);
}

# check to make sure we are running within a CWIS installation
$BootstrapFile = "include/StartUp.php";
if (!is_readable($BootstrapFile)
        || (!is_readable("config.php") && !is_readable("local/config.php")))
{
    print "Must be run from the base directory of a working CWIS installation.\n";
    exit(1);
}

# print help message if no arguments supplied
if (count($argv) < 2)
{
    PrintHelp();
    exit(0);
}

# set up operating environment
require_once("include/StartUp.php");

# check to make sure we have at least the minimum required CWIS version
if (!version_compare(CWIS_VERSION, $GLOBALS["CCLURequiredCwisVersion"], ">="))
{
    print "CWIS version ".$GLOBALS["CCLURequiredCwisVersion"]
            ." or later is required.\n";
    exit(1);
}

# grab command and command arguments
$Command = strtolower($argv[1]);
$Args = array_slice($argv, 2);
$ArgLetter = (count($Args) && strlen($Args[0])) ? strtoupper($Args[0][0]) : NULL;

switch ($Command)
{
    # CLEAR ALL CACHES
    case "clearcache":
    case "clearcaches":
        if (strpos("ATOP", $ArgLetter) !== FALSE)
        {
            switch ($ArgLetter)
            {
                case "A":
                    $GLOBALS["AF"]->ClearTemplateLocationCache();
                    $GLOBALS["AF"]->ClearObjectLocationCache();
                    $GLOBALS["AF"]->ClearPageCache();
                    print "All caches cleared.";
                    break;

                case "T":
                    $GLOBALS["AF"]->ClearTemplateLocationCache();
                    print "Template location cache cleared.";
                    break;

                case "O":
                    $GLOBALS["AF"]->ClearObjectLocationCache();
                    print "Object location cache cleared.";
                    break;

                case "P":
                    $GLOBALS["AF"]->ClearPageCache();
                    print "Page cache cleared.";
                    break;
            }
        }
        else
        {
            print "Usage: cwis clearcache (all|template|object|page)\n";
        }
        break;

    # SET DEFAULT INTERFACE
    case "defaultui":
        $NewInterface = isset($Args[0]) ? $Args[0] : NULL;
        $InterfaceList = $GLOBALS["AF"]->GetUserInterfaces();
        if (isset($InterfaceList[$NewInterface]))
        {
            $GLOBALS["G_SysConfig"]->DefaultActiveUI($NewInterface);
            print "Default interface set to \"".$NewInterface."\".";
        }
        else
        {
            if (strlen($NewInterface))
            {
                print "Unknown interface \"".$NewInterface."\".\n";
            }
            print "Usage: cwis defaultui CanonicalInterfaceName\n";
        }
        break;

    # LIST SCHEMAS
    case "lschema":
    case "lschemas":
        $Schemas = MetadataSchema::GetAllSchemas();
        usort($Schemas, function($A, $B)
        {
            return ($A->Id() < $B->Id()) ? -1 : 1;
        });
        printf("%2s %-30s\n", "ID", "SCHEME NAME");
        foreach ($Schemas as $Schema)
        {
            printf("%2d %-30s\n", $Schema->Id(), $Schema->Name());
        }
        break;

    # PLUGIN ENABLE/DISABLE
    case "penable":
    case "pdisable":
        if ($ArgLetter)
        {
            $PluginName = $Args[0];
            $Plugin = $GLOBALS["G_PluginManager"]->GetPlugin($PluginName, TRUE);
        }
        else
        {
            $Plugin = NULL;
        }
        if ($Plugin === NULL)
        {
            if (isset($PluginName))
            {
                print "No plugin found with the name \"".$PluginName."\".\n";
            }
            print "Usage: cwis ".$Command." PluginName\n";
            exit(1);
        }
        $Plugin->IsEnabled(($Command == "penable") ? TRUE : FALSE);
        print "Plugin \"".$PluginName."\" has been "
                .(($Command == "penable") ? "enabled" : "disabled")
                .".\n";
        break;

    # LIST TASKS CURRENTLY IN QUEUE
    case "tlist":
        if (strpos("QRO", $ArgLetter) !== FALSE)
        {
            switch ($ArgLetter)
            {
                case "Q":
                    $Tasks = $GLOBALS["AF"]->GetQueuedTaskList();
                    $QueueSize = $GLOBALS["AF"]->GetTaskQueueSize();
                    print "Tasks in Queue: ".$QueueSize."\n";
                    break;

                case "R":
                    $Tasks = $GLOBALS["AF"]->GetRunningTaskList();
                    $QueueSize = count($Tasks);
                    print "Currently Running Tasks: ".$QueueSize."\n";
                    break;

                case "O":
                    $Tasks = $GLOBALS["AF"]->GetOrphanedTaskList();
                    $QueueSize = count($Tasks);
                    print "Orphaned Tasks: ".$QueueSize."\n";
                    break;
            }

            if ($QueueSize)
            {
                printf("%-9s %-40s\n", "ID", "SYNOPSIS");
                foreach ($Tasks as $TaskId => $TaskInfo)
                {
                    $TaskSynopsis = htmlspecialchars_decode(
                            ApplicationFramework::GetTaskCallbackSynopsis($TaskInfo));
                    printf("%-9d %-40s\n", $TaskId, $TaskSynopsis);
                }
            }
        }
        else
        {
            print "Usage: cwis tlist (queued|running|orphaned)\n";
        }
        break;

    # ADD/REMOVE USER PRIVILEGE
    case "upriv":
        if ((strpos("ARL", $ArgLetter) !== FALSE)
                && ((count($Args) >= 3)
                        || ((count($Args) == 2) && ($ArgLetter == "L"))))
        {
            $UserName = $Args[1];
            $UFactory = new UserFactory();
            if ($UFactory->UserNameExists($UserName))
            {
                $User = new CWUser($UserName);
            }
            else
            {
                print "User name \"".$UserName."\" is unknown.\n";
                exit(1);
            }

            if (($ArgLetter == "A") || ($ArgLetter == "R"))
            {
                $PrivilegeName = strtoupper($Args[2]);
                $PFactory = new PrivilegeFactory();
                if ((strpos($PrivilegeName, "PRIV_") === 0) && defined($PrivilegeName))
                {
                    $Privilege = constant($PrivilegeName);
                }
                elseif (defined("PRIV_".$PrivilegeName))
                {
                    $Privilege = constant("PRIV_".$PrivilegeName);
                    $PrivilegeName = "PRIV_".$PrivilegeName;
                }
                elseif (is_numeric($PrivilegeName)
                        && $PFactory->ItemExists($PrivilegeName))
                {
                    $Privilege = $PrivilegeName;
                    $PrivObj = new Privilege($Privilege);
                    $PrivilegeName = $PrivObj->Name();
                }
                else
                {
                    print "Privilege \"".$PrivilegeName."\" is unknown.\n";
                    exit(1);
                }
            }

            switch ($ArgLetter)
            {
                case "A":
                    $User->GrantPriv($Privilege);
                    print "Privilege ".$PrivilegeName
                            ." given to user ".$UserName.".\n";
                    break;

                case "R":
                    $User->RevokePriv($Privilege);
                    print "Privilege ".$PrivilegeName
                            ." removed from user ".$UserName.".\n";
                    break;

                case "L":
                    print "Current privileges for user ".$UserName.":\n";
                    $CurrPrivs = $User->GetPrivList();
                    # (get all constants that begin with "PRIV_")
                    $PrivConstants = array_filter(get_defined_constants(),
                            function ($Key) {
                                    return is_string($Key)
                                            && (strpos($Key, "PRIV_") === 0);
                                    },
                            ARRAY_FILTER_USE_KEY);
                    $PrivNamesDefault = array();
                    $PrivNamesCustom = array();
                    foreach ($CurrPrivs as $Priv)
                    {
                        $PrivName = array_search($Priv, $PrivConstants);
                        if ($PrivName !== FALSE)
                        {
                            $PrivNamesDefault[$Priv] = $PrivName;
                        }
                        else
                        {
                            $PrivObj = new Privilege($Priv);
                            $PrivNamesCustom[$Priv] = $PrivObj->Name();
                        }
                    }
                    asort($PrivNamesDefault);
                    asort($PrivNamesCustom);
                    $CurrPrivNames = $PrivNamesDefault + $PrivNamesCustom;
                    foreach ($CurrPrivNames as $Priv => $PrivName)
                    {
                        if (strpos($PrivName, "PRIV_") === 0)
                        {
                            print "    ".$PrivName."\n";
                        }
                        else
                        {
                            print "    ".$PrivName." (".$Priv.")\n";
                        }
                    }
                    break;
            }
        }
        else
        {
            print "Usage: cwis upriv (add|remove|list) username [privilege]\n";
            print "Examples:\n";
            print "    cwis upriv add someuser classadmin\n";
            print "    cwis upriv r someuser priv_sysadmin\n";
            print "    cwis upriv a someuser 102\n";
        }
        break;

    default:
        print "Unknown command \"".$Command."\"\n";
        PrintHelp();
        exit(1);
}

