<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* END LICENSE
*
* Used to create and manipulate a profile and work directory from the
* command-line for Yioop.
*
* @author Chris Pollett chris@pollett.org
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*/
namespace seekquarry\yioop\configs;
use seekquarry\yioop\library as L;
use seekquarry\yioop\library\CrawlConstants;
use seekquarry\yioop\controllers\AdminController;
if (php_sapi_name() != 'cli' ||
defined("seekquarry\\yioop\\configs\\IS_OWN_WEB_SERVER")) {
echo "BAD REQUEST"; exit();
}
/** Loads common utility functions*/
require_once __DIR__."/../library/Utility.php";
/** Loads common constants for web crawling*/
require_once __DIR__."/../library/LocaleFunctions.php";
mb_internal_encoding("UTF-8");
mb_regex_encoding("UTF-8");
/**
* shorthand for echo
*
* @param string $text string to send to the current output
*/
function e($text)
{
echo $text;
}
$locale_tag = L\guessLocale();
$locale = null;
L\setLocaleObject($locale_tag);
/**
* Provides a command-line interface way to configure a Yioop Instance.
* Unlike the web interface this interface is English-only.
*/
class ConfigureTool
{
/**
* Used to hold an AdminController object used to manipulate the
* Yioop configuration
* @var object
*/
public $admin;
/**
* Holds the main menu data for the configuration tool
* @var array
*/
public $menu = ["workDirectory" => "Create/Set Work Directory",
"rootPassword" => "Change root password",
"defaultLocale"=> "Set Default Locale",
"upgradeLocales" => "Upgrade Locales",
"debugDisplay"=> "Debug Display Set-up",
"searchAccess"=> "Search Access Set-up",
"searchPageElementLinks" => "Search Page Elements and Links",
"nameServer" => "Name Server Set-up",
"robotSetUp"=> "Crawl Robot Set-up",
"quit" => "Exit program"
];
/**
* To change configuration parameters of Yioop, this program
* invokes AdminController methods. These methods expect, data
* passed to them in super globals set up as a result of an HTTP
* request. This program fakes the settings of these variables.
* To keep things simple this constructor initializes each of the
* relevant super globals to be empty arrays.
*/
function __construct()
{
$_REQUEST = [];
$_POST = [];
$_GET = [];
$_SERVER = [];
$_SESSION = [];
$this->admin = new AdminController();
}
/**
* This is the main loop where options of what the user can configure
* are presented, a choice is requested, and so on...
*/
function loop()
{
$done = false;
$activities = array_keys($this->menu);
$activities[] = "configureMenu";
$state = "configureMenu";
while($state != "quit") {
if (in_array($state, $activities) ) {
$state = $this->$state();
}
}
}
/**
* This is used to draw the main configuration menu and ask for a
* user selection
* @return string name of the next menu state (e.g.
* "workDirectory", "quit") chosen by the user
*/
function configureMenu()
{
$this->banner();
$data = $this->callConfigure();
e("Checking Yioop configuration...".
"\n===============================\n");
$check_status = str_replace("<br>", "\n", $data["SYSTEM_CHECK"]);
e($check_status."\n===============================\n");
$items = ["workDirectory" => "Create/Set Work Directory",
"quit" => "Exit program"];
if ($data["PROFILE"]) {
$items = $this->menu;
}
return $this->drawChooseItems($items, "configureMenu");
}
/**
* Used to create/change the location of this Yioop instances work
* directory
* @return string name of the next menu state to dispatch to after
* the work-directory step
*/
function workDirectory()
{
$this->banner();
$data = $this->callConfigure();
$directory = (isset($data["WORK_DIRECTORY"]) &&
$data["WORK_DIRECTORY"] != "") ? $data["WORK_DIRECTORY"]
: "";
/* The path an empty entry will use: the directory already in
effect when there is one, otherwise the default location
next to the Yioop folder. */
$default_directory = ($directory != "") ? $directory :
DEFAULT_WORK_DIRECTORY;
$is_initialized = file_exists($default_directory .
PROFILE_FILE_NAME);
if ($directory != "") {
e("CURRENT WORK DIRECTORY: $directory\n\n");
} else {
e("CURRENT WORK DIRECTORY: none set yet\n\n");
}
if (!$is_initialized) {
e("This work directory has not been initialized yet ".
"(no profile found at\n$default_directory).\n\n");
}
e("Enter a new value, or just press return to ".
"create/reinitialize the\ncurrent work directory at ".
"$default_directory:\n");
if (!isset($_SERVER['REQUEST_URI'])) {
$_SERVER['REQUEST_URI'] = "";
}
$this->prepareGlobals($data);
$entered = trim(L\readInput());
if ($entered == "") {
$entered = $default_directory;
}
$_REQUEST["WORK_DIRECTORY"] = $entered;
$_REQUEST["arg"] = "directory";
$next_menu = $this->confirmChange("configure", "workDirectory");
return $next_menu;
}
/**
* Used to change the password of the root account of this Yioop Instance
* @return string name of the next menu state to dispatch to after
* the root-password step
*/
function rootPassword()
{
$this->banner();
$data = $this->callConfigure();
if ($data["PROFILE"] != 1) {
$_REQUEST["MESSAGE"] = "Work directory needs to be set/created!";
return "configureMenu";
}
e("Enter old password:");
$_REQUEST["password"] = L\readPassword();
e("Enter new password:");
$_REQUEST["new_password"] = L\readPassword();
e("Re-Enter new password:");
$_REQUEST["retype_password"] = L\readPassword();
$_SESSION['USER_ID'] = ROOT_ID;
$_REQUEST['arg'] = "updateuser";
$_REQUEST['edit_pass'] = "true";
$next_menu = $this->confirmChange("manageAccount", "rootPassword");
return $next_menu;
}
/**
* Changes the default locale (language) used by Yioop when it cannot
* determine that information from the user's browser
* @return string name of the next menu state to dispatch to after
* the default-locale step
*/
function defaultLocale()
{
$this->banner();
$data = $this->callConfigure();
if ($data["PROFILE"] != 1) {
$_REQUEST["MESSAGE"] = "Work directory needs to be set/created!";
return "configureMenu";
}
e("CURRENT LANGUAGE: ".$data["LANGUAGES"][
$data["DEFAULT_LOCALE"]]."\n\n");
$_SESSION = [];
$items = $data["LANGUAGES"];
$items["configureMenu"] = "Return to Main Menu";
do {
$choice = $this->drawChooseItems($items, "defaultLocale");
} while( $choice == "defaultLocale");
$this->prepareGlobals($data);
if ($choice == "configureMenu") {
$_REQUEST = [];
$_SERVER = [];
return "configureMenu";
}
$_REQUEST["DEFAULT_LOCALE"] = $choice;
return "defaultLocale";
}
/**
* Used to configure debugging information for this Yioop instance.
* i.e., whether PHP notices, warnings, errors, should be displayed,
* whether query statistics and info should be displayed, and whether
* unit tests should be viewable from the web
* @return string name of the next menu state to dispatch to after
* the debug-display step
*/
function debugDisplay()
{
$this->banner();
$data = $this->callConfigure();
if ($data["PROFILE"] != 1) {
$_REQUEST["MESSAGE"] = "Work directory needs to be set/created!";
return "configureMenu";
}
e("CURRENT DEBUG SETTINGS\n======================\n");
$dlevel = $data["DEBUG_LEVEL"];
$setting = ($dlevel & ERROR_INFO) ? "On" : "Off";
e("Error Info: [$setting]\n");
$setting = ($dlevel & QUERY_INFO) ? "On" : "Off";
e("Query Info: [$setting]\n");
$setting = ($dlevel & TEST_INFO) ? "On" : "Off";
e("Test Info: [$setting]\n");
$items = ["ERROR_INFO" => "Toggle Error Info",
"QUERY_INFO" => "Toggle Query Info",
"TEST_INFO" => "Toggle Test Info",
"configureMenu" => "Return to Main Menu"];
do {
$choice = $this->drawChooseItems($items, "debugDisplay");
} while( $choice == "debugDisplay");
$this->prepareGlobals($data);
if ($choice == "configureMenu") {
$_REQUEST = [];
$_SERVER = [];
return "configureMenu";
}
$flag = constant(NS_CONFIGS . $choice);
$dlevel = ($dlevel & $flag) ? $dlevel - $flag : $dlevel + $flag;
if ($dlevel & ERROR_INFO) {$_REQUEST["ERROR_INFO"] = "true";}
if ($dlevel & QUERY_INFO) {$_REQUEST["QUERY_INFO"] = "true";}
if ($dlevel & TEST_INFO) {$_REQUEST["TEST_INFO"] = "true";}
return "debugDisplay";
}
/**
* Configures which methods are allowed by this Yioop instance to access
* search results, (via the web, via open rss search results, via the
* API)
* @return string name of the next menu state to dispatch to after
* the search-access step
*/
function searchAccess()
{
$this->banner();
$data = $this->callConfigure();
if ($data["PROFILE"] != 1) {
$_REQUEST["MESSAGE"] = "Work directory needs to be set/created!";
return "configureMenu";
}
e("CURRENT SEARCH ACCESS SETTINGS\n==============================\n");
$settings = ["WEB_ACCESS" => "Web",
"RSS_ACCESS" => "RSS", "API_ACCESS" => "API"];
$items = [];
foreach ($settings as $setting => $setting_string) {
$toggle = ($data[$setting]) ? "On" : "Off";
e("$setting_string: [$toggle]\n");
$items[$setting] = "Toggle $setting_string";
}
$items["configureMenu"] = "Return to Main Menu";
do {
$choice = $this->drawChooseItems($items, "searchAccess");
} while( $choice == "searchAccess");
$this->prepareGlobals($data);
if ($choice == "configureMenu") {
$_REQUEST = [];
$_SERVER = [];
return "configureMenu";
}
$_REQUEST[$choice] = ($data[$choice]) ? false : true;
return "searchAccess";
}
/**
* Configures which of the various links of the SERPS page such as
* Cache, etc should be displayed. Also, configures whether the signin
* links, etc should be displayed.
* @return string name of the next menu state to dispatch to after
* the search-page-elements step
*/
function searchPageElementLinks()
{
$this->banner();
$data = $this->callConfigure();
if ($data["PROFILE"] != 1) {
$_REQUEST["MESSAGE"] = "Work directory needs to be set/created!";
return "configureMenu";
}
e("CURRENT SEARCH PAGE ELEMENTS AND LINKS SETTINGS".
"\n===================================================\n");
$settings = ["WORD_SUGGEST" => "Word Suggest",
"SUBSEARCH_LINK" => "Subsearch Links",
"SIGNIN_LINK" => "Sign-in Links",
"MORE_RESULT" => "More Result Info",
"CACHE_LINK" => "Cache Link",
"SIMILAR_LINK" => "Similar Link", "IN_LINK" => "Inlinks",
"IP_LINK"=> "IP Links"];
$items = [];
foreach ($settings as $setting => $setting_string) {
$toggle = ($data[$setting]) ? "On" : "Off";
e("$setting_string: [$toggle]\n");
$items[$setting] = "Toggle $setting_string";
}
$items["configureMenu"] = "Return to Main Menu";
do {
$choice = $this->drawChooseItems($items, "searchPageElementLinks");
} while( $choice == "searchPageElementLinks");
$this->prepareGlobals($data);
if ($choice == "configureMenu") {
$_REQUEST = [];
$_SERVER = [];
return "configureMenu";
}
$_REQUEST[$choice] = ($data[$choice]) ? false : true;
return "searchPageElementLinks";
}
/**
* Configures settings relating to the location of the name server and
* the salt used when communicating with it. Also, configures caching
* mechanisms the name server should use when returning results.
* @return string name of the next menu state to dispatch to after
* the name-server step
*/
function nameServer()
{
$this->banner();
$data = $this->callConfigure();
if ($data["PROFILE"] != 1) {
$_REQUEST["MESSAGE"] = "Work directory needs to be set/created!";
return "configureMenu";
}
e("NAME SERVER SETTINGS\n====================\n");
e("Server Key: [".$data["AUTH_KEY"]."]\n");
e("Name Server URL: [".$data["NAME_SERVER"]."]\n");
$settings = ["USE_FILECACHE" => "Use File Cache"];
$items = ["serverKey" => "Edit Server Key",
"nameServer" => "Edit Name Server Url"];
foreach ($settings as $setting => $setting_string) {
$toggle = ($data[$setting]) ? "On" : "Off";
e("$setting_string: [$toggle]\n");
$items[$setting] = "Toggle $setting_string";
}
$items["configureMenu"] = "Return to Main Menu";
do {
$choice = $this->drawChooseItems($items, "nameServerMenu");
} while( $choice == "nameServerMenu");
$this->prepareGlobals($data);
switch ($choice) {
case "configureMenu":
$_REQUEST = [];
$_SERVER = [];
return "configureMenu";
break;
case "serverKey":
e("Enter a new server key: ");
$_REQUEST["AUTH_KEY"] = L\readInput();
break;
case "nameServer":
e("Enter a new name server url: ");
$_REQUEST["NAME_SERVER"] = L\readInput();
break;
default:
$_REQUEST[$choice] = ($data[$choice]) ? false : true;
}
return "nameServer";
}
/**
* Used to set up the name of this instance of the Yioop robot as well
* as its description page.
* @return string name of the next menu state to dispatch to after
* the robot-set-up step
*/
function robotSetUp()
{
$this->banner();
$data = $this->callConfigure();
if ($data["PROFILE"] != 1) {
$_REQUEST["MESSAGE"] = "Work directory needs to be set/created!";
return "configureMenu";
}
e("CRAWL ROBOT SETTINGS\n====================\n");
e("Crawl Robot Name: [".$data["USER_AGENT_SHORT"]."]\n");
e("Robot Instance: [".$data["ROBOT_INSTANCE"]."]\n");
e("\nRobot Description:\n=================\n".
$data["ROBOT_DESCRIPTION"] . "\n=================\n");
$items = ["robotName" => "Edit Robot Name",
"robotInstance" => "Edit Robot Instance",
"robotDescription" => "Edit Robot Description",
"configureMenu" => "Return to Main Menu"];
do {
$choice = $this->drawChooseItems($items, "robotSetUp");
} while( $choice == "robotSetUp");
$this->prepareGlobals($data);
switch ($choice) {
case "configureMenu":
$_REQUEST = [];
$_SERVER = [];
return "configureMenu";
break;
case "robotName":
e("Enter a new robot name: ");
$_REQUEST["USER_AGENT_SHORT"] = L\readInput();
break;
case "robotInstance":
e("Enter a new robot instance value: ");
$_REQUEST["ROBOT_INSTANCE"] = L\readInput();
break;
case "robotDescription":
e("Enter a description of your web crawler robot.\n".
"Terminate input with a line with only '.' on it:\n");
$_REQUEST["ROBOT_DESCRIPTION"] = L\readMessage();
break;
}
return "robotSetUp";
}
/**
* Used to select to confirm, cancel, or re-enter the last profile
* change
*
* @param string $admin_method to call if confirmed
* @param string $reenter_method , return value if reenter chosen
* @return string menu name to do to next
*/
function confirmChange($admin_method, $reenter_method)
{
$component_activities = AdminController::$component_activities;
$items = ["confirm" => "Confirm Change",
"reenter" => "Re-enter the information",
"configureMenu" => "Return to the Configure Menu"];
$first = true;
do {
$choice = $this->drawChooseItems($items, "confirmChange");
} while( $choice == "confirmChange");
switch ($choice) {
case "confirm":
$component = "system";
foreach ($component_activities as $available_component =>
$activities) {
if (in_array($admin_method, $activities)) {
$component = $available_component;
break;
}
}
$data = $this->admin->component($component)->$admin_method();
$_SERVER = [];
$_SESSION = [];
$_REQUEST = [];
$_REQUEST["MESSAGE"] = $data["MESSAGE"];
$next_menu = "configureMenu";
break;
case "reenter":
$_SERVER = [];
$_SESSION = [];
$_REQUEST = [];
$next_menu = $reenter_method;
break;
default:
$_SERVER = [];
$_SESSION = [];
$_REQUEST = [];
$next_menu = "configureMenu";
}
return $next_menu;
}
/**
* Interactive menu step, and the action behind the upgrade-locales
* command, that force-pushes the locale strings together with the
* version-gated wiki and help pages and resource locale files from
* the source tree into the work directory, regardless of the stored
* resources-wiki version. This lets a developer see edited help
* pages and resource files during ongoing work without bumping the
* resources-wiki version on every change. The outcome is reported
* through the usual menu message so both the menu and the command
* surface the same line.
*
* @return string name of the next menu state, the main menu
*/
function upgradeLocales()
{
require_once __DIR__ . "/../library/UpgradeFunctions.php";
L\upgradeLocales(true);
$_REQUEST["MESSAGE"] = "Locale strings and wiki resources " .
"force-pushed from the source tree into the work directory.";
return "configureMenu";
}
/**
* Runs one configuration command from values given on the command
* line, with no prompting. It sets up the request the way the
* matching interactive step would, fills in the answer that step
* would ask for from the supplied values, and saves the change.
* The work-directory command is allowed to run on a fresh install;
* every other command first needs a work directory to exist, and
* prints a message and stops when one does not.
*
* @param string $command the command name the user typed
* @param array $spec the command's specification (its activity and
* argument rules)
* @param array $values the arguments the user gave after the
* command name
*/
function runActivityFromArgs($command, $spec, $values)
{
$data = $this->callConfigure();
if ($command != "work-dir" &&
(!isset($data["PROFILE"]) || $data["PROFILE"] != 1)) {
e("A work directory must be set up first. Run:\n");
e(" php ConfigureTool.php work-dir <path>\n");
return;
}
if ($command == "work-dir") {
$directory = (isset($data["WORK_DIRECTORY"]) &&
$data["WORK_DIRECTORY"] != "") ?
$data["WORK_DIRECTORY"] : DEFAULT_WORK_DIRECTORY;
$entered = (count($values) == 1 && trim($values[0]) != "") ?
trim($values[0]) : $directory;
$_REQUEST["WORK_DIRECTORY"] = $entered;
$_REQUEST["arg"] = "directory";
$this->commitActivity("configure", $data);
return;
}
if ($command == "root-password") {
$_REQUEST["password"] = $values[0];
$_REQUEST["new_password"] = $values[1];
$_REQUEST["retype_password"] = $values[1];
$_SESSION['USER_ID'] = ROOT_ID;
$_REQUEST['arg'] = "updateuser";
$_REQUEST['edit_pass'] = "true";
$this->commitActivity("manageAccount", $data);
return;
}
if ($command == "locale") {
$this->prepareGlobals($data);
$_REQUEST["DEFAULT_LOCALE"] = $values[0];
$this->commitActivity("configure", $data);
return;
}
if ($command == "name-server") {
$this->prepareGlobals($data);
$_REQUEST["AUTH_KEY"] = $values[0];
$_REQUEST["NAME_SERVER"] = $values[1];
$this->commitActivity("configure", $data);
return;
}
if ($command == "robot") {
$this->prepareGlobals($data);
$_REQUEST["USER_AGENT_SHORT"] = $values[0];
$_REQUEST["ROBOT_INSTANCE"] = $values[1];
$_REQUEST["ROBOT_DESCRIPTION"] = $values[2];
$this->commitActivity("configure", $data);
return;
}
if ($command == "upgrade-locales") {
$this->upgradeLocales();
e($_REQUEST["MESSAGE"] . "\n");
return;
}
/* The remaining commands turn named settings on with +name or
off with -name, leaving anything not listed unchanged. The
name-to-request-key maps below match the labels each
interactive step shows. */
$toggle_settings = [
"debug" => ["error" => "ERROR_INFO",
"query" => "QUERY_INFO", "test" => "TEST_INFO"],
"search-access" => ["web" => "WEB_ACCESS",
"rss" => "RSS_ACCESS", "api" => "API_ACCESS"],
"page-elements" => ["word-suggest" => "WORD_SUGGEST",
"subsearch" => "SUBSEARCH_LINK",
"signin" => "SIGNIN_LINK", "result-info" => "MORE_RESULT",
"cache" => "CACHE_LINK", "similar" => "SIMILAR_LINK",
"inlink" => "IN_LINK", "ip" => "IP_LINK"],
];
$this->runToggleFromArgs($command, $toggle_settings[$command],
$values, $data);
}
/**
* Saves a setting change that turns named on/off options on with
* +name or off with -name. The starting point is the current
* setting, so anything the user does not name keeps its present
* value. An unrecognized name prints the usage help and stops.
*
* @param string $command the command name the user typed
* @param array $setting_names maps each accepted short name to the
* request key that stores its setting
* @param array $values the +name / -name arguments the user gave
* @param array $data the current profile state
*/
function runToggleFromArgs($command, $setting_names, $values, $data)
{
$this->prepareGlobals($data);
/* start every setting at its current value so unnamed ones do
not change. */
foreach ($setting_names as $short_name => $request_key) {
if (!empty($data[$request_key])) {
$_REQUEST[$request_key] = "true";
} else {
unset($_REQUEST[$request_key]);
}
}
foreach ($values as $value) {
$sign = substr($value, 0, 1);
$short_name = substr($value, 1);
if (($sign != "+" && $sign != "-") ||
!isset($setting_names[$short_name])) {
e("Bad option: $value\n\n");
configureToolUsage();
return;
}
$request_key = $setting_names[$short_name];
if ($sign == "+") {
$_REQUEST[$request_key] = "true";
} else {
unset($_REQUEST[$request_key]);
}
}
$this->commitActivity("configure", $data);
}
/**
* Saves the change set up in the request by calling the admin
* activity that handles it, the same one the interactive Confirm
* choice would call. Prints the result message the activity
* returns.
*
* @param string $admin_method the admin activity to run, such as
* configure or manageAccount
* @param array $data the current profile state, used to find which
* part of the admin controller owns the activity
*/
function commitActivity($admin_method, $data)
{
$component_activities = AdminController::$component_activities;
$component = "system";
foreach ($component_activities as $available_component =>
$activities) {
if (in_array($admin_method, $activities)) {
$component = $available_component;
break;
}
}
$result = $this->admin->component($component)->$admin_method();
if (!empty($result["MESSAGE"])) {
e($result["MESSAGE"] . "\n");
}
}
/**
* Draws a list of options to the screen and gets a choice
* from this list from the user.
*
* @param array $items as associative array (return value => description)
* @param string $currentView value to return if invalid choice made
* @return string a choice from the user
*/
function drawChooseItems($items, $currentView)
{
$choice_nums = [];
$i = 1;
e("\nAvailable Options:\n==================\n");
foreach ($items as $name => $description) {
e("($i) $description\n");
$choice_nums[$i] = $name;
$i++;
}
if (!empty($_REQUEST["MESSAGE"])) {
e("\n+++ ".$_REQUEST["MESSAGE"]." +++\n");
unset($_REQUEST["MESSAGE"]);
}
e("\nPlease choose an option:\n");
$user_data = strtolower(trim(L\readInput()));
if ($user_data >= 1 && $user_data < $i) {
$_REQUEST["MESSAGE"] = "";
return $choice_nums[$user_data];
} else {
$_REQUEST["MESSAGE"] = "Invalid choice. Please choose again.";
return $currentView;
}
}
/**
* Used to call system components configure method. It detects if
* a redirect happened by the fact that $data['PROFILE'] is not set.
* If so it passes along the redirect message and re-calls configure()
* @return array \$data array as returned by the Admin
* controller's configure activity (system check, current
* profile, locale fields)
*/
function callConfigure()
{
$data = $this->admin->component("system")->configure();
if (!isset($data["PROFILE"])) {
$_REQUEST = [];
$message = (isset($data['MESSAGE'])) ? $data['MESSAGE'] : "";
$data = $this->admin->component("system")->configure();
$data['MESSAGE'] = $message;
}
return $data;
}
/**
* Prints the banner used by this configuration tool
*/
function banner()
{
e(chr(27) . "[2J" . chr(27) . "[;H");
e("\n\nYIOOP! CONFIGURATION TOOL\n");
e("+++++++++++++++++++++++++\n\n");
}
/**
* Sets-up the field values of the super globals used by AdminController
* when changing a profile or managing passwords. These particular
* values don't change with respect to what this tool does.
*
* @param array $data current profile state
*/
function prepareGlobals($data)
{
$_SESSION = [];
$_REQUEST = $this->copyProfileFields($data);
$_REQUEST["arg"] = "profile";
$_REQUEST['YIOOP_TOKEN'] = "";
if (!isset($_SERVER['REQUEST_URI'])) {
if (!empty($data['WEB_URI'])) {
$_SERVER['REQUEST_URI'] = $data['WEB_URI'];
} else {
e("Enter web path for Yioop instance:\n");
$_SERVER['REQUEST_URI'] = L\readInput();
}
}
}
/**
* Used to copy the contents of $data which are profile fields to a
* new array.
*
* @param array $data an array of profile and other fields
* @return array a new array containing a copy of just the profile fields
* from the original array
*/
function copyProfileFields($data)
{
$profile = [];
foreach ($this->admin->model("profile")->profile_fields as $field) {
if (isset($data[$field])) {
$profile[$field] = $data[$field];
}
}
return $profile;
}
}
/**
* The set of commands the tool understands from the command line. Each
* entry maps a short command name to: the activity method it runs, the
* list of arguments that command takes (for the help text and for
* checking the count given), the smallest and largest number of
* arguments allowed, and a one-line description. Toggle-style commands
* take any number of +name / -name arguments to turn settings on or
* off, so their range is open-ended.
*
* @return array the command specifications keyed by command name
*/
function configureToolCommands()
{
return [
"work-dir" => ["activity" => "workDirectory",
"args" => "[path]", "min" => 0, "max" => 1,
"help" => "Set or create the work directory (no path ".
"means the default location)."],
"root-password" => ["activity" => "rootPassword",
"args" => "<old> <new>", "min" => 2, "max" => 2,
"help" => "Change the root account password."],
"locale" => ["activity" => "defaultLocale",
"args" => "<tag>", "min" => 1, "max" => 1,
"help" => "Set the default language, such as en-US."],
"debug" => ["activity" => "debugDisplay",
"args" => "[+/-error] [+/-query] [+/-test]",
"min" => 1, "max" => 3,
"help" => "Turn debug outputs on (+) or off (-)."],
"search-access" => ["activity" => "searchAccess",
"args" => "[+/-web] [+/-rss] [+/-api]",
"min" => 1, "max" => 3,
"help" => "Turn search-access methods on (+) or off (-)."],
"page-elements" => ["activity" => "searchPageElementLinks",
"args" => "[+/-word-suggest] [+/-subsearch] ".
"[+/-signin] [+/-result-info]\n ".
"[+/-cache] [+/-similar] [+/-inlink] [+/-ip]",
"min" => 1, "max" => 99,
"help" => "Turn search-page elements and links on (+) ".
"or off (-)."],
"name-server" => ["activity" => "nameServer",
"args" => "<key> <url>", "min" => 2, "max" => 2,
"help" => "Set the server key and name-server URL."],
"robot" => ["activity" => "robotSetUp",
"args" => "<name> <instance> <description>",
"min" => 3, "max" => 3,
"help" => "Set the crawl robot name, instance, and ".
"description."],
"upgrade-locales" => ["activity" => "upgradeLocales",
"args" => "", "min" => 0, "max" => 0,
"help" => "Force-push locale strings and wiki resources ".
"from the source tree (no version bump needed)."],
];
}
/**
* Prints how to run the configuration tool from the command line: with
* no arguments to see this help, with the word menu to use the
* interactive menu, or with a command name and its arguments to run
* that one step without prompting. Each command is listed with the
* arguments it takes and a one-line description.
*/
function configureToolUsage()
{
e("Yioop Configuration Tool\n");
e("========================\n\n");
e("Usage:\n");
e(" php ConfigureTool.php\n");
e(" show this help\n");
e(" php ConfigureTool.php menu\n");
e(" run the interactive menu\n");
e(" php ConfigureTool.php <command> [arguments...]\n");
e(" run one command without prompting\n\n");
e("Commands:\n");
foreach (configureToolCommands() as $name => $spec) {
e(" $name " . $spec["args"] . "\n");
e(" " . $spec["help"] . "\n");
}
}
$configure_tool = new ConfigureTool();
if (empty($argv[1])) {
configureToolUsage();
} else if ($argv[1] == "menu") {
$configure_tool->loop();
} else {
$commands = configureToolCommands();
if (!isset($commands[$argv[1]])) {
e("Unknown command: " . $argv[1] . "\n\n");
configureToolUsage();
} else {
$spec = $commands[$argv[1]];
$values = array_slice($argv, 2);
if (count($values) < $spec["min"] ||
count($values) > $spec["max"]) {
e("Wrong number of arguments for " . $argv[1] . ".\n\n");
configureToolUsage();
} else {
$configure_tool->runActivityFromArgs($argv[1], $spec,
$values);
}
}
}