mirror of
https://github.com/processwire/processwire.git
synced 2025-08-18 12:31:17 +02:00
Update PW installer to use Uikit 3 theme, plus add support for detecting and dropping existing tables (if present) during installation.
This commit is contained in:
460
install.php
460
install.php
@@ -11,7 +11,7 @@
|
|||||||
* If that file exists, the installer will not run. So if you need to re-run this installer for any
|
* If that file exists, the installer will not run. So if you need to re-run this installer for any
|
||||||
* reason, then you'll want to delete that file. This was implemented just in case someone doesn't delete the installer.
|
* reason, then you'll want to delete that file. This was implemented just in case someone doesn't delete the installer.
|
||||||
*
|
*
|
||||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
* ProcessWire 3.x, Copyright 2017 by Ryan Cramer
|
||||||
* https://processwire.com
|
* https://processwire.com
|
||||||
*
|
*
|
||||||
* @todo have installer set session name
|
* @todo have installer set session name
|
||||||
@@ -57,7 +57,7 @@ class Installer {
|
|||||||
/**
|
/**
|
||||||
* File permissions, determined in the dbConfig function
|
* File permissions, determined in the dbConfig function
|
||||||
*
|
*
|
||||||
* Below are last resort defaults
|
* Below are worst case scenario, last resort defaults
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected $chmodDir = "0777";
|
protected $chmodDir = "0777";
|
||||||
@@ -69,6 +69,14 @@ class Installer {
|
|||||||
*/
|
*/
|
||||||
protected $numErrors = 0;
|
protected $numErrors = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when we are in a section
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $inSection = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Available color themes
|
* Available color themes
|
||||||
*
|
*
|
||||||
@@ -91,11 +99,11 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// these two vars used by install-head.inc
|
// these two vars used by install-head.inc
|
||||||
$title = "ProcessWire " . PROCESSWIRE_INSTALL . " Installation";
|
$title = "ProcessWire " . PROCESSWIRE_INSTALL . " Installer";
|
||||||
$formAction = "./install.php";
|
$formAction = "./install.php";
|
||||||
if($title && $formAction) {} // ignore
|
if($title && $formAction) {} // ignore
|
||||||
|
|
||||||
require("./wire/modules/AdminTheme/AdminThemeDefault/install-head.inc");
|
require("./wire/modules/AdminTheme/AdminThemeUikit/install-head.inc");
|
||||||
|
|
||||||
if(isset($_POST['step'])) switch($_POST['step']) {
|
if(isset($_POST['step'])) switch($_POST['step']) {
|
||||||
|
|
||||||
@@ -118,7 +126,7 @@ class Installer {
|
|||||||
|
|
||||||
} else $this->welcome();
|
} else $this->welcome();
|
||||||
|
|
||||||
require("./wire/modules/AdminTheme/AdminThemeDefault/install-foot.inc");
|
require("./wire/modules/AdminTheme/AdminThemeUikit/install-foot.inc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -200,6 +208,7 @@ class Installer {
|
|||||||
$out = '';
|
$out = '';
|
||||||
$profiles = $this->findProfiles();
|
$profiles = $this->findProfiles();
|
||||||
if(!count($profiles)) $this->err("No profiles found!");
|
if(!count($profiles)) $this->err("No profiles found!");
|
||||||
|
|
||||||
foreach($profiles as $name => $profile) {
|
foreach($profiles as $name => $profile) {
|
||||||
$title = empty($profile['title']) ? ucfirst($profile['name']) : $profile['title'];
|
$title = empty($profile['title']) ? ucfirst($profile['name']) : $profile['title'];
|
||||||
//$selected = $name == 'site-default' ? " selected='selected'" : "";
|
//$selected = $name == 'site-default' ? " selected='selected'" : "";
|
||||||
@@ -222,12 +231,15 @@ class Installer {
|
|||||||
If you are just getting started with ProcessWire, we recommend choosing
|
If you are just getting started with ProcessWire, we recommend choosing
|
||||||
the <em>Default</em> site profile. If you already know what you are doing,
|
the <em>Default</em> site profile. If you already know what you are doing,
|
||||||
you might prefer the <em>Blank</em> site profile.
|
you might prefer the <em>Blank</em> site profile.
|
||||||
<p>
|
<p style='width: 240px;'>
|
||||||
<select name='profile' id='select-profile'>
|
<select class='uk-select' name='profile' id='select-profile'>
|
||||||
<option value=''>Installation Profiles</option>
|
<option value=''>Installation Profiles</option>
|
||||||
$options
|
$options
|
||||||
</select>
|
</select>
|
||||||
<span class='detail'><i class='fa fa-angle-left'></i> Select each installation profile to see more information and a preview.</span>
|
</p>
|
||||||
|
<p class='detail'>
|
||||||
|
<i class='fa fa-angle-up'></i>
|
||||||
|
Select each installation profile to see more information and a preview.
|
||||||
</p>
|
</p>
|
||||||
$out
|
$out
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
@@ -246,20 +258,20 @@ class Installer {
|
|||||||
*/
|
*/
|
||||||
protected function initProfile() {
|
protected function initProfile() {
|
||||||
|
|
||||||
$this->h('Site Installation Profile');
|
$this->h('Site Installation Profile', 'building-o');
|
||||||
|
|
||||||
if(is_file("./site/install/install.sql")) {
|
if(is_file("./site/install/install.sql")) {
|
||||||
$this->ok("Found installation profile in /site/install/");
|
$this->alertOk("Found installation profile in /site/install/");
|
||||||
|
|
||||||
} else if(is_dir("./site/")) {
|
} else if(is_dir("./site/")) {
|
||||||
$this->ok("Found /site/ -- already installed? ");
|
$this->alertOk("Found /site/ — already installed? ");
|
||||||
|
|
||||||
} else if(isset($_POST['profile'])) {
|
} else if(isset($_POST['profile'])) {
|
||||||
|
|
||||||
$profiles = $this->findProfiles();
|
$profiles = $this->findProfiles();
|
||||||
$profile = preg_replace('/[^-a-zA-Z0-9_]/', '', $_POST['profile']);
|
$profile = preg_replace('/[^-a-zA-Z0-9_]/', '', $_POST['profile']);
|
||||||
if(empty($profile) || !isset($profiles[$profile]) || !is_dir(dirname(__FILE__) . "/$profile")) {
|
if(empty($profile) || !isset($profiles[$profile]) || !is_dir(dirname(__FILE__) . "/$profile")) {
|
||||||
$this->err("Profile not found");
|
$this->alertErr("Profile not found");
|
||||||
$this->selectProfile();
|
$this->selectProfile();
|
||||||
$this->btn("Continue", 0);
|
$this->btn("Continue", 0);
|
||||||
return;
|
return;
|
||||||
@@ -268,9 +280,9 @@ class Installer {
|
|||||||
// $this->h(empty($info['title']) ? ucfirst($info['name']) : $info['title']);
|
// $this->h(empty($info['title']) ? ucfirst($info['name']) : $info['title']);
|
||||||
|
|
||||||
if(@rename("./$profile", "./site")) {
|
if(@rename("./$profile", "./site")) {
|
||||||
$this->ok("Renamed /$profile => /site");
|
$this->alertOk("Renamed /$profile => /site");
|
||||||
} else {
|
} else {
|
||||||
$this->err("File system is not writable by this installer. Before continuing, please rename '/$profile' to '/site'");
|
$this->alertErr("File system is not writable by this installer. Before continuing, please rename '/$profile' to '/site'");
|
||||||
$this->btn("Continue", 0);
|
$this->btn("Continue", 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -290,7 +302,7 @@ class Installer {
|
|||||||
*/
|
*/
|
||||||
protected function compatibilityCheck() {
|
protected function compatibilityCheck() {
|
||||||
|
|
||||||
$this->h("Compatibility Check");
|
$this->sectionStart('fa-gears Compatibility Check');
|
||||||
|
|
||||||
if(version_compare(PHP_VERSION, self::MIN_REQUIRED_PHP_VERSION) >= 0) {
|
if(version_compare(PHP_VERSION, self::MIN_REQUIRED_PHP_VERSION) >= 0) {
|
||||||
$this->ok("PHP version " . PHP_VERSION);
|
$this->ok("PHP version " . PHP_VERSION);
|
||||||
@@ -371,6 +383,7 @@ class Installer {
|
|||||||
} else {
|
} else {
|
||||||
$this->ok(".htaccess looks good");
|
$this->ok(".htaccess looks good");
|
||||||
}
|
}
|
||||||
|
$this->sectionStop();
|
||||||
|
|
||||||
if($this->numErrors) {
|
if($this->numErrors) {
|
||||||
$this->p("One or more errors were found above. We recommend you correct these issues before proceeding or <a href='http://processwire.com/talk/'>contact ProcessWire support</a> if you have questions or think the error is incorrect. But if you want to proceed anyway, click Continue below.");
|
$this->p("One or more errors were found above. We recommend you correct these issues before proceeding or <a href='http://processwire.com/talk/'>contact ProcessWire support</a> if you have questions or think the error is incorrect. But if you want to proceed anyway, click Continue below.");
|
||||||
@@ -385,16 +398,36 @@ class Installer {
|
|||||||
* Step 2: Configure the database and file permission settings
|
* Step 2: Configure the database and file permission settings
|
||||||
*
|
*
|
||||||
* @param array $values
|
* @param array $values
|
||||||
|
* @param int $hasNumTables
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function dbConfig($values = array()) {
|
protected function dbConfig($values = array(), $hasNumTables = 0) {
|
||||||
|
|
||||||
if(!is_file("./site/install/install.sql")) die("There is no installation profile in /site/. Please place one there before continuing. You can get it at processwire.com/download");
|
if(!is_file("./site/install/install.sql")) die(
|
||||||
|
"There is no installation profile in /site/. Please place one there before continuing. " .
|
||||||
|
"You can get it at https://processwire.com/download/"
|
||||||
|
);
|
||||||
|
|
||||||
|
if($hasNumTables) {
|
||||||
|
$this->sectionStart('fa-database Existing tables action');
|
||||||
|
// select($name, $label, $value, array $options) {
|
||||||
|
$this->p("What would you like to do with the existing database tables that are present?");
|
||||||
|
$this->select('dbTablesAction', '', 0, array(
|
||||||
|
'0' => "Click to select tables action",
|
||||||
|
'ignore' => "Ignore tables*",
|
||||||
|
'remove' => "Remove tables",
|
||||||
|
), 0);
|
||||||
|
$this->p("*When choosing “Ignore tables”, existing tables having the same name as newly imported tables will still be deleted.", 'detail');
|
||||||
|
$this->sectionStop();
|
||||||
|
}
|
||||||
|
|
||||||
$this->h("MySQL Database");
|
$this->sectionStart('fa-database MySQL Database');
|
||||||
$this->p("Please specify a MySQL 5.x database and user account on your server. If the database does not exist, we will attempt to create it. If the database already exists, the user account should have full read, write and delete permissions on the database.*");
|
$this->p(
|
||||||
$this->p("*Recommended permissions are select, insert, update, delete, create, alter, index, drop, create temporary tables, and lock tables.", "detail");
|
"Please specify a MySQL 5.x+ database and user account on your server. If the database does not exist, " .
|
||||||
|
"we will attempt to create it. If the database already exists, the user account should have full read, " .
|
||||||
|
"write and delete permissions on the database (recommended permissions are select, insert, update, delete, " .
|
||||||
|
"create, alter, index, drop, create temporary tables, and lock tables)."
|
||||||
|
);
|
||||||
|
|
||||||
if(!isset($values['dbName'])) $values['dbName'] = '';
|
if(!isset($values['dbName'])) $values['dbName'] = '';
|
||||||
// @todo: are there PDO equivalents for the ini_get()s below?
|
// @todo: are there PDO equivalents for the ini_get()s below?
|
||||||
@@ -407,6 +440,8 @@ class Installer {
|
|||||||
if(!$values['dbHost']) $values['dbHost'] = 'localhost';
|
if(!$values['dbHost']) $values['dbHost'] = 'localhost';
|
||||||
if(!$values['dbPort']) $values['dbPort'] = 3306;
|
if(!$values['dbPort']) $values['dbPort'] = 3306;
|
||||||
if(empty($values['dbCharset'])) $values['dbCharset'] = 'utf8';
|
if(empty($values['dbCharset'])) $values['dbCharset'] = 'utf8';
|
||||||
|
if($values['dbCharset'] != 'utf8mb4') $values['dbCharset'] = 'utf8';
|
||||||
|
if($values['dbEngine'] != 'InnoDB') $values['dbEngine'] = 'MyISAM';
|
||||||
|
|
||||||
foreach($values as $key => $value) {
|
foreach($values as $key => $value) {
|
||||||
if(strpos($key, 'chmod') === 0) {
|
if(strpos($key, 'chmod') === 0) {
|
||||||
@@ -416,39 +451,22 @@ class Installer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$this->input('dbName', 'DB Name', $values['dbName']);
|
$this->input('dbName', 'DB Name', $values['dbName']);
|
||||||
$this->input('dbUser', 'DB User', $values['dbUser']);
|
$this->input('dbUser', 'DB User', $values['dbUser']);
|
||||||
$this->input('dbPass', 'DB Pass', $values['dbPass'], false, 'password', false);
|
$this->input('dbPass', 'DB Pass', $values['dbPass'], false, 'password', false);
|
||||||
$this->input('dbHost', 'DB Host', $values['dbHost']);
|
$this->input('dbHost', 'DB Host', $values['dbHost'], false);
|
||||||
$this->input('dbPort', 'DB Port', $values['dbPort'], true);
|
$this->input('dbPort', 'DB Port', $values['dbPort']);
|
||||||
|
|
||||||
echo
|
$this->select('dbCharset', 'DB Charset', $values['dbCharset'], array('utf8', 'utf8mb4'));
|
||||||
"<div id='dbAdvancedToggle'><small>" .
|
$this->select('dbEngine', 'DB Engine', $values['dbEngine'], array('MyISAM', 'InnoDB'));
|
||||||
"<a class='ui-priority-secondary' href='#' onclick='$(\"#dbAdvanced\").slideDown();$(\"#dbAdvancedToggle\").slideUp();'>" .
|
$this->clear();
|
||||||
"<i class='fa fa-wrench'></i> Advanced: Charset & Engine …</a>" .
|
|
||||||
"</small></div>";
|
|
||||||
|
|
||||||
echo "<div id='dbAdvanced' style='display: none'>";
|
|
||||||
$this->h('Advanced Database Options');
|
|
||||||
$this->p(
|
$this->p(
|
||||||
"The 'utf8' and 'MyISAM' options are known to work across the broadest range of servers and 3rd party modules, " .
|
"The DB Charset option “utf8mb4” may not be compatible with all 3rd party modules.<br />" .
|
||||||
"so you should not change these settings unless you know what you are doing. " .
|
"The DB Engine option “InnoDB” requires MySQL 5.6.4 or newer.",
|
||||||
"The 'utf8mb4' (charset) and/or 'InnoDB' (engine) may be preferable for some installations. " .
|
array('class' => 'detail', 'style' => 'margin-top:0')
|
||||||
"*Please note the 'InnoDB' option requires MySQL 5.6.4 or newer."
|
|
||||||
);
|
);
|
||||||
echo "<p style='width: 135px; float: left; margin-top: 0;'><label>DB Charset</label><br />";
|
$this->sectionStop();
|
||||||
echo "<select name='dbCharset'>";
|
|
||||||
echo "<option value='utf8'" . ($values['dbCharset'] != 'utf8mb4' ? " selected" : "") . ">utf8</option>";
|
|
||||||
echo "<option value='utf8mb4'" . ($values['dbCharset'] == 'utf8mb4' ? " selected" : "") . ">utf8mb4</option>";
|
|
||||||
echo "</select></p>";
|
|
||||||
// $this->input('dbCharset', 'DB Charset', $values['dbCharset']);
|
|
||||||
echo "<p style='width: 135px; float: left; margin-top: 0;'><label>DB Engine</label><br />";
|
|
||||||
echo "<select name='dbEngine'>";
|
|
||||||
echo "<option value='MyISAM'" . ($values['dbEngine'] != 'InnoDB' ? " selected" : "") . ">MyISAM</option>";
|
|
||||||
echo "<option value='InnoDB'" . ($values['dbEngine'] == 'InnoDB' ? " selected" : "") . ">InnoDB*</option>";
|
|
||||||
echo "</select></p>";
|
|
||||||
echo "</div>";
|
|
||||||
|
|
||||||
$cgi = false;
|
$cgi = false;
|
||||||
$defaults = array();
|
$defaults = array();
|
||||||
@@ -485,18 +503,12 @@ class Installer {
|
|||||||
|
|
||||||
$values = array_merge($defaults, $values);
|
$values = array_merge($defaults, $values);
|
||||||
|
|
||||||
$this->h("Default Time Zone");
|
$this->sectionStart('fa-globe Time Zone');
|
||||||
echo "<p><select name='timezone'>";
|
$this->p('The time zone selection should be consistent with the time zone of the web server you are installing to.');
|
||||||
foreach($this->timezones() as $key => $timezone) {
|
$this->selectTimezone($values['timezone']);
|
||||||
$label = $timezone;
|
$this->sectionStop();
|
||||||
if(strpos($label, '|')) list($label, $timezone) = explode('|', $label);
|
|
||||||
$selected = $timezone == $values['timezone'] ? "selected='selected'" : '';
|
|
||||||
$label = str_replace('_', ' ', $label);
|
|
||||||
echo "<option value=\"$key\" $selected>$label</option>";
|
|
||||||
}
|
|
||||||
echo "</select></p>";
|
|
||||||
|
|
||||||
$this->h("File Permissions");
|
$this->sectionStart("fa-key File Permissions");
|
||||||
$this->p(
|
$this->p(
|
||||||
"When ProcessWire creates directories or files, it assigns permissions to them. " .
|
"When ProcessWire creates directories or files, it assigns permissions to them. " .
|
||||||
"Enter the most restrictive permissions possible that give ProcessWire (and you) read and write access to the web server (Apache). " .
|
"Enter the most restrictive permissions possible that give ProcessWire (and you) read and write access to the web server (Apache). " .
|
||||||
@@ -511,19 +523,27 @@ class Installer {
|
|||||||
$this->input('chmodFile', 'Files', $values['chmodFile'], true);
|
$this->input('chmodFile', 'Files', $values['chmodFile'], true);
|
||||||
|
|
||||||
if($cgi) {
|
if($cgi) {
|
||||||
echo "<p class='detail' style='margin-top: 0;'>We detected that this file (install.php) is writable. That means Apache may be running as your user account. Given that, we populated the permissions above (755 & 644) as possible starting point.</p>";
|
$this->p(
|
||||||
|
"We detected that this file (install.php) is writable. That means Apache may be running as your user account. Given that, we populated the permissions above (755 & 644) as possible starting point.",
|
||||||
|
array('class' => 'detail', 'style' => 'margin-top:0')
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
echo "<p class='detail' style='margin-top: 0;'>WARNING: 777 and 666 permissions mean that directories and files are readable and writable to everyone on the server (and thus not particularly safe). If in any kind of shared hosting environment, please consult your web host for their recommended permission settings for Apache readable/writable directories and files before proceeding. <a target='_blank' href='https://processwire.com/docs/security/file-permissions/'>More</a></p>";
|
$this->p(
|
||||||
|
"WARNING: 777 and 666 permissions mean that directories and files are readable and writable to everyone on the server (and thus not particularly safe). If in any kind of shared hosting environment, please consult your web host for their recommended permission settings for Apache readable/writable directories and files before proceeding. " .
|
||||||
|
"<a target='_blank' href='https://processwire.com/docs/security/file-permissions/'>More</a>",
|
||||||
|
array('class' => 'detail', 'style' => 'margin-top:0')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->h("HTTP Host Names");
|
$this->sectionStop();
|
||||||
|
|
||||||
|
$this->sectionStart('fa-server HTTP Host Names');
|
||||||
$this->p("What host names will this installation run on now and in the future? Please enter one host per line. You may also choose to leave this blank to auto-detect on each request, but we recommend using this whitelist for the best security in production environments.");
|
$this->p("What host names will this installation run on now and in the future? Please enter one host per line. You may also choose to leave this blank to auto-detect on each request, but we recommend using this whitelist for the best security in production environments.");
|
||||||
$this->p("This field is recommended but not required. You can set this later by editing the file <u>/site/config.php</u> (setting \$config->httpHosts).", "detail");
|
$this->p("This field is recommended but not required. You can set this later by editing the file <u>/site/config.php</u> (setting \$config->httpHosts).", "detail");
|
||||||
$rows = substr_count($values['httpHosts'], "\n") + 2;
|
$rows = substr_count($values['httpHosts'], "\n") + 2;
|
||||||
echo "<p><textarea name='httpHosts' rows='$rows' style='width: 100%;'>" . htmlentities($values['httpHosts'], ENT_QUOTES, 'UTF-8') . "</textarea></p>";
|
$this->textarea('httpHosts', '', $values['httpHosts'], $rows);
|
||||||
|
$this->sectionStop();
|
||||||
$this->btn("Continue", 4);
|
$this->btn("Continue", 4);
|
||||||
|
|
||||||
$this->p("Note: After you click the button above, be patient … it may take a minute.", "detail");
|
$this->p("Note: After you click the button above, be patient … it may take a minute.", "detail");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +560,7 @@ class Installer {
|
|||||||
$fields = array('chmodDir', 'chmodFile');
|
$fields = array('chmodDir', 'chmodFile');
|
||||||
foreach($fields as $field) {
|
foreach($fields as $field) {
|
||||||
$value = (int) $_POST[$field];
|
$value = (int) $_POST[$field];
|
||||||
if(strlen("$value") !== 3) $this->err("Value for '$field' is invalid");
|
if(strlen("$value") !== 3) $this->alertErr("Value for '$field' is invalid");
|
||||||
else $this->$field = "0$value";
|
else $this->$field = "0$value";
|
||||||
$values[$field] = $value;
|
$values[$field] = $value;
|
||||||
}
|
}
|
||||||
@@ -572,6 +592,7 @@ class Installer {
|
|||||||
|
|
||||||
// db configuration
|
// db configuration
|
||||||
$fields = array('dbUser', 'dbName', 'dbPass', 'dbHost', 'dbPort', 'dbEngine', 'dbCharset');
|
$fields = array('dbUser', 'dbName', 'dbPass', 'dbHost', 'dbPort', 'dbEngine', 'dbCharset');
|
||||||
|
|
||||||
foreach($fields as $field) {
|
foreach($fields as $field) {
|
||||||
$value = get_magic_quotes_gpc() ? stripslashes($_POST[$field]) : $_POST[$field];
|
$value = get_magic_quotes_gpc() ? stripslashes($_POST[$field]) : $_POST[$field];
|
||||||
$value = substr($value, 0, 255);
|
$value = substr($value, 0, 255);
|
||||||
@@ -581,11 +602,10 @@ class Installer {
|
|||||||
|
|
||||||
$values['dbCharset'] = ($values['dbCharset'] === 'utf8mb4' ? 'utf8mb4' : 'utf8');
|
$values['dbCharset'] = ($values['dbCharset'] === 'utf8mb4' ? 'utf8mb4' : 'utf8');
|
||||||
$values['dbEngine'] = ($values['dbEngine'] === 'InnoDB' ? 'InnoDB' : 'MyISAM');
|
$values['dbEngine'] = ($values['dbEngine'] === 'InnoDB' ? 'InnoDB' : 'MyISAM');
|
||||||
// if(!ctype_alnum($values['dbCharset'])) $values['dbCharset'] = 'utf8';
|
|
||||||
|
|
||||||
if(!$values['dbUser'] || !$values['dbName'] || !$values['dbPort']) {
|
if(!$values['dbUser'] || !$values['dbName'] || !$values['dbPort']) {
|
||||||
|
|
||||||
$this->err("Missing database configuration fields");
|
$this->alertErr("Missing database configuration fields");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -607,8 +627,8 @@ class Installer {
|
|||||||
$database = $this->dbCreateDatabase($dsn, $values, $driver_options);
|
$database = $this->dbCreateDatabase($dsn, $values, $driver_options);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->err("Database connection information did not work.");
|
$this->alertErr("Database connection information did not work.");
|
||||||
$this->err($e->getMessage());
|
$this->alertErr(htmlentities($e->getMessage(), ENT_QUOTES, 'UTF-8'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -618,24 +638,55 @@ class Installer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->h("Test Database and Save Configuration");
|
$this->h("fa-database Test Database and Save Configuration");
|
||||||
$this->ok("Database connection successful to " . htmlspecialchars($values['dbName']));
|
$this->alertOk("Database connection successful to " . htmlspecialchars($values['dbName']));
|
||||||
|
|
||||||
$options = array(
|
$options = array(
|
||||||
'dbCharset' => strtolower($values['dbCharset']),
|
'dbCharset' => strtolower($values['dbCharset']),
|
||||||
'dbEngine' => $values['dbEngine']
|
'dbEngine' => $values['dbEngine']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// check if MySQL is new enough to support InnoDB with fulltext indexes
|
||||||
if($options['dbEngine'] == 'InnoDB') {
|
if($options['dbEngine'] == 'InnoDB') {
|
||||||
$query = $database->query("SELECT VERSION()");
|
$query = $database->query("SELECT VERSION()");
|
||||||
list($dbVersion) = $query->fetch(\PDO::FETCH_NUM);
|
list($dbVersion) = $query->fetch(\PDO::FETCH_NUM);
|
||||||
if(version_compare($dbVersion, "5.6.4", "<")) {
|
if(version_compare($dbVersion, "5.6.4", "<")) {
|
||||||
$options['dbEngine'] = 'MyISAM';
|
$options['dbEngine'] = 'MyISAM';
|
||||||
$values['dbEngine'] = 'MyISAM';
|
$values['dbEngine'] = 'MyISAM';
|
||||||
$this->err("Your MySQL version is $dbVersion and InnoDB requires 5.6.4 or newer. Engine changed to MyISAM.");
|
$this->alertErr("Your MySQL version is $dbVersion and InnoDB requires 5.6.4 or newer. Engine changed to MyISAM.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->dbSaveConfigFile($values)) {
|
// check if database already has tables present
|
||||||
|
$query = $database->query("SHOW TABLES");
|
||||||
|
$tables = $query->fetchAll(\PDO::FETCH_COLUMN);
|
||||||
|
$numTables = count($tables);
|
||||||
|
$dbTablesAction = isset($_POST['dbTablesAction']) ? $_POST['dbTablesAction'] : '';
|
||||||
|
|
||||||
|
if($numTables && $dbTablesAction) {
|
||||||
|
if($dbTablesAction === 'remove') {
|
||||||
|
// remove
|
||||||
|
foreach($tables as $table) {
|
||||||
|
$database->exec("DROP TABLE `$table`");
|
||||||
|
}
|
||||||
|
$this->alertOk("Dropped $numTables existing table(s)");
|
||||||
|
$numTables = 0;
|
||||||
|
} else if($dbTablesAction === 'ignore') {
|
||||||
|
// ignore
|
||||||
|
$this->alertOk('Existing tables will be ignored');
|
||||||
|
} else {
|
||||||
|
$dbTablesAction = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($numTables && empty($dbTablesAction)) {
|
||||||
|
$this->alertErr(
|
||||||
|
"<strong>Database already has $numTables table(s) present:</strong> " .
|
||||||
|
implode(', ', $tables) . ". " .
|
||||||
|
"<strong>Please select below what you would like to do with these tables.</strong>"
|
||||||
|
);
|
||||||
|
$this->dbConfig($values, $numTables);
|
||||||
|
} else if($this->dbSaveConfigFile($values)) {
|
||||||
$this->profileImport($database, $options);
|
$this->profileImport($database, $options);
|
||||||
} else {
|
} else {
|
||||||
$this->dbConfig($values);
|
$this->dbConfig($values);
|
||||||
@@ -674,17 +725,17 @@ class Installer {
|
|||||||
$database->exec("CREATE SCHEMA IF NOT EXISTS `$dbName` DEFAULT CHARACTER SET `$dbCharset`");
|
$database->exec("CREATE SCHEMA IF NOT EXISTS `$dbName` DEFAULT CHARACTER SET `$dbCharset`");
|
||||||
// reconnect
|
// reconnect
|
||||||
$database = new \PDO($dsn, $values['dbUser'], $values['dbPass'], $driver_options);
|
$database = new \PDO($dsn, $values['dbUser'], $values['dbPass'], $driver_options);
|
||||||
if($database) $this->ok("Created database: $dbName");
|
if($database) $this->alertOk("Created database: $dbName");
|
||||||
|
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
$this->err("Failed to create database with name $dbName");
|
$this->alertErr("Failed to create database with name $dbName");
|
||||||
$this->err($e->getMessage());
|
$this->alertErr($e->getMessage());
|
||||||
$database = null;
|
$database = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$database = null;
|
$database = null;
|
||||||
$this->err("Unable to create database with that name. Please create the database with another tool and try again.");
|
$this->alertErr("Unable to create database with that name. Please create the database with another tool and try again.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $database;
|
return $database;
|
||||||
@@ -740,6 +791,12 @@ class Installer {
|
|||||||
"\n\$config->timezone = '$values[timezone]';" .
|
"\n\$config->timezone = '$values[timezone]';" .
|
||||||
"\n" .
|
"\n" .
|
||||||
"\n/**" .
|
"\n/**" .
|
||||||
|
"\n * Installer: Admin theme" .
|
||||||
|
"\n * " .
|
||||||
|
"\n */" .
|
||||||
|
"\n\$config->defaultAdminTheme = 'AdminThemeUikit';" .
|
||||||
|
"\n" .
|
||||||
|
"\n/**" .
|
||||||
"\n * Installer: Unix timestamp of date/time installed" .
|
"\n * Installer: Unix timestamp of date/time installed" .
|
||||||
"\n * " .
|
"\n * " .
|
||||||
"\n * This is used to detect which when certain behaviors must be backwards compatible." .
|
"\n * This is used to detect which when certain behaviors must be backwards compatible." .
|
||||||
@@ -762,10 +819,10 @@ class Installer {
|
|||||||
|
|
||||||
if(($fp = fopen("./site/config.php", "a")) && fwrite($fp, $cfg)) {
|
if(($fp = fopen("./site/config.php", "a")) && fwrite($fp, $cfg)) {
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
$this->ok("Saved configuration to ./site/config.php");
|
$this->alertOk("Saved configuration to ./site/config.php");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
$this->err("Error saving configuration to ./site/config.php. Please make sure it is writable.");
|
$this->alertErr("Error saving configuration to ./site/config.php. Please make sure it is writable.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -780,7 +837,7 @@ class Installer {
|
|||||||
protected function profileImport($database, array $options) {
|
protected function profileImport($database, array $options) {
|
||||||
|
|
||||||
if(self::TEST_MODE) {
|
if(self::TEST_MODE) {
|
||||||
$this->ok("TEST MODE: Skipping profile import");
|
$this->alertOk("TEST MODE: Skipping profile import");
|
||||||
$this->adminAccount();
|
$this->adminAccount();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -788,6 +845,8 @@ class Installer {
|
|||||||
$profile = "./site/install/";
|
$profile = "./site/install/";
|
||||||
if(!is_file("{$profile}install.sql")) die("No installation profile found in {$profile}");
|
if(!is_file("{$profile}install.sql")) die("No installation profile found in {$profile}");
|
||||||
|
|
||||||
|
$this->sectionStart('fa-building-o Profile Import');
|
||||||
|
|
||||||
// checks to see if the database exists using an arbitrary query (could just as easily be something else)
|
// checks to see if the database exists using an arbitrary query (could just as easily be something else)
|
||||||
try {
|
try {
|
||||||
$query = $database->prepare("SHOW COLUMNS FROM pages");
|
$query = $database->prepare("SHOW COLUMNS FROM pages");
|
||||||
@@ -831,7 +890,7 @@ class Installer {
|
|||||||
} else {
|
} else {
|
||||||
// they are installing site-default already
|
// they are installing site-default already
|
||||||
}
|
}
|
||||||
|
$this->sectionStop();
|
||||||
$this->adminAccount();
|
$this->adminAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,7 +953,7 @@ class Installer {
|
|||||||
$replace = array();
|
$replace = array();
|
||||||
if($options['dbEngine'] != 'MyISAM') {
|
if($options['dbEngine'] != 'MyISAM') {
|
||||||
$replace['ENGINE=MyISAM'] = "ENGINE=$options[dbEngine]";
|
$replace['ENGINE=MyISAM'] = "ENGINE=$options[dbEngine]";
|
||||||
$this->warn("Engine changed to '$options[dbEngine]', please keep an eye out for issues.");
|
// $this->alertWarn("Engine changed to '$options[dbEngine]', please keep an eye out for issues.");
|
||||||
}
|
}
|
||||||
if($options['dbCharset'] != 'utf8') {
|
if($options['dbCharset'] != 'utf8') {
|
||||||
$replace['CHARSET=utf8'] = "CHARSET=$options[dbCharset]";
|
$replace['CHARSET=utf8'] = "CHARSET=$options[dbCharset]";
|
||||||
@@ -906,7 +965,7 @@ class Installer {
|
|||||||
$replace['(255)'] = '(250)'; // max ley length in utf8mb4 is 1000 (250 * 4)
|
$replace['(255)'] = '(250)'; // max ley length in utf8mb4 is 1000 (250 * 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->warn("Character set has been changed to '$options[dbCharset]', please keep an eye out for issues.");
|
// $this->alertWarn("Character set has been changed to '$options[dbCharset]', please keep an eye out for issues.");
|
||||||
}
|
}
|
||||||
if(count($replace)) $restoreOptions['findReplaceCreateTable'] = $replace;
|
if(count($replace)) $restoreOptions['findReplaceCreateTable'] = $replace;
|
||||||
require("./wire/core/WireDatabaseBackup.php");
|
require("./wire/core/WireDatabaseBackup.php");
|
||||||
@@ -916,7 +975,7 @@ class Installer {
|
|||||||
$this->ok("Imported database file: $file1");
|
$this->ok("Imported database file: $file1");
|
||||||
$this->ok("Imported database file: $file2");
|
$this->ok("Imported database file: $file2");
|
||||||
} else {
|
} else {
|
||||||
foreach($backup->errors() as $error) $this->err($error);
|
foreach($backup->errors() as $error) $this->alertErr($error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -944,25 +1003,41 @@ class Installer {
|
|||||||
$clean[$key] = $value;
|
$clean[$key] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->h("Admin Panel Information");
|
$this->sectionStart("fa-sign-in Admin Panel");
|
||||||
$this->input("admin_name", "Admin Login URL", $clean['admin_name'], false, "name");
|
$this->input("admin_name", "Admin Login URL", $clean['admin_name'], false, "name");
|
||||||
|
/*
|
||||||
$js = "$('link#colors').attr('href', $('link#colors').attr('href').replace(/main-.*$/, 'main-' + $(this).val() + '.css'))";
|
$js = "$('link#colors').attr('href', $('link#colors').attr('href').replace(/main-.*$/, 'main-' + $(this).val() + '.css'))";
|
||||||
echo "<p class='ui-helper-clearfix'><label>Color Theme<br /><select name='colors' id='colors' onchange=\"$js\">";
|
echo "<p class='ui-helper-clearfix'><label>Color Theme<br /><select name='colors' id='colors' onchange=\"$js\">";
|
||||||
foreach($this->colors as $color) echo "<option value='$color'>" . ucfirst($color) . "</option>";
|
foreach($this->colors as $color) echo "<option value='$color'>" . ucfirst($color) . "</option>";
|
||||||
echo "</select></label> <span class='detail'><i class='fa fa-angle-left'></i> Change for a live preview</span></p>";
|
echo "</select></label> <span class='detail'><i class='fa fa-angle-left'></i> Change for a live preview</span></p>";
|
||||||
|
*/
|
||||||
|
$this->clear();
|
||||||
|
|
||||||
$this->p("<i class='fa fa-info-circle'></i> You can change the admin URL later by editing the admin page and changing the name on the settings tab.<br /><i class='fa fa-info-circle'></i> You can change the colors later by going to Admin <i class='fa fa-angle-right'></i> Modules <i class='fa fa-angle-right detail'></i> Core <i class='fa fa-angle-right detail'></i> Admin Theme <i class='fa fa-angle-right'></i> Settings.", "detail");
|
$this->p(
|
||||||
$this->h("Admin Account Information");
|
"fa-info-circle You can change the admin URL later by editing the admin page and changing the name on the settings tab.",
|
||||||
$this->p("You will use this account to login to your ProcessWire admin. It will have superuser access, so please make sure to create a <a target='_blank' href='http://en.wikipedia.org/wiki/Password_strength'>strong password</a>.");
|
array('class' => 'detail', 'style' => 'margin-top:0')
|
||||||
|
);
|
||||||
|
$this->sectionStop();
|
||||||
|
|
||||||
|
$this->sectionStart("fa-user-circle Admin Account");
|
||||||
|
$this->p(
|
||||||
|
"You will use this account to login to your ProcessWire admin. It will have superuser access, so please make sure " .
|
||||||
|
"to create a <a target='_blank' href='http://en.wikipedia.org/wiki/Password_strength'>strong password</a>."
|
||||||
|
);
|
||||||
$this->input("username", "User", $clean['username'], false, "name");
|
$this->input("username", "User", $clean['username'], false, "name");
|
||||||
$this->input("userpass", "Password", $clean['userpass'], false, "password");
|
$this->input("userpass", "Password", $clean['userpass'], false, "password");
|
||||||
$this->input("userpass_confirm", "Password <small class='detail'>(again)</small>", $clean['userpass_confirm'], true, "password");
|
$this->input("userpass_confirm", "Password <small class='detail'>(again)</small>", $clean['userpass_confirm'], false, "password");
|
||||||
$this->input("useremail", "Email Address", $clean['useremail'], true, "email");
|
$this->input("useremail", "Email Address", $clean['useremail'], true, "email");
|
||||||
$this->p("<i class='fa fa-warning'></i> Please remember the password you enter above as you will not be able to retrieve it again.", "detail");
|
$this->p(
|
||||||
|
"fa-warning Please remember the password you enter above as you will not be able to retrieve it again.",
|
||||||
|
array('class' => 'detail', 'style' => 'margin-top:0')
|
||||||
|
);
|
||||||
|
$this->sectionStop();
|
||||||
|
|
||||||
$this->h("Cleanup");
|
$this->sectionStart("fa-bath Cleanup");
|
||||||
$this->p("Directories and files listed below are no longer needed and should be removed. If you choose to leave any of them in place, you should delete them before migrating to a production environment.", "detail");
|
$this->p("Directories and files listed below are no longer needed and should be removed. If you choose to leave any of them in place, you should delete them before migrating to a production environment.", "detail");
|
||||||
$this->p($this->getRemoveableItems($wire, true));
|
$this->p($this->getRemoveableItems($wire, true));
|
||||||
|
$this->sectionStop();
|
||||||
|
|
||||||
$this->btn("Continue", 5);
|
$this->btn("Continue", 5);
|
||||||
}
|
}
|
||||||
@@ -1009,7 +1084,7 @@ class Installer {
|
|||||||
$note = $disabled ? "<span class='detail'>(not writable/deletable by this installer)</span>" : "";
|
$note = $disabled ? "<span class='detail'>(not writable/deletable by this installer)</span>" : "";
|
||||||
$markup =
|
$markup =
|
||||||
"<label style='font-weight: normal;'>" .
|
"<label style='font-weight: normal;'>" .
|
||||||
"<input type='checkbox' $checked $disabled name='remove_items[]' value='$name' /> $item[label] $note" .
|
"<input class='uk-checkbox' type='checkbox' $checked $disabled name='remove_items[]' value='$name' /> $item[label] $note" .
|
||||||
"</label>";
|
"</label>";
|
||||||
$items[$name]['markup'] = $markup;
|
$items[$name]['markup'] = $markup;
|
||||||
$out .= $out ? "<br />$markup" : $markup;
|
$out .= $out ? "<br />$markup" : $markup;
|
||||||
@@ -1050,6 +1125,7 @@ class Installer {
|
|||||||
|
|
||||||
$input = $wire->input;
|
$input = $wire->input;
|
||||||
$sanitizer = $wire->sanitizer;
|
$sanitizer = $wire->sanitizer;
|
||||||
|
$adminTheme = $wire->modules->getInstall('AdminThemeUikit');
|
||||||
|
|
||||||
if(!$input->post('username') || !$input->post('userpass')) $this->err("Missing account information");
|
if(!$input->post('username') || !$input->post('userpass')) $this->err("Missing account information");
|
||||||
if($input->post('userpass') !== $input->post('userpass_confirm')) $this->err("Passwords do not match");
|
if($input->post('userpass') !== $input->post('userpass_confirm')) $this->err("Passwords do not match");
|
||||||
@@ -1085,6 +1161,7 @@ class Installer {
|
|||||||
$user->name = $username;
|
$user->name = $username;
|
||||||
$user->pass = $input->post('userpass');
|
$user->pass = $input->post('userpass');
|
||||||
$user->email = $email;
|
$user->email = $email;
|
||||||
|
$user->admin_theme = $adminTheme;
|
||||||
|
|
||||||
if(!$user->roles->has("superuser")) $user->roles->add($superuserRole);
|
if(!$user->roles->has("superuser")) $user->roles->add($superuserRole);
|
||||||
|
|
||||||
@@ -1108,9 +1185,10 @@ class Installer {
|
|||||||
|
|
||||||
$adminName = htmlentities($adminName, ENT_QUOTES, "UTF-8");
|
$adminName = htmlentities($adminName, ENT_QUOTES, "UTF-8");
|
||||||
|
|
||||||
$this->h("Admin Account Saved");
|
$this->sectionStart("fa-user-circle Admin Account Saved");
|
||||||
$this->ok("User account saved: <b>{$user->name}</b>");
|
$this->ok("User account saved: <b>{$user->name}</b>");
|
||||||
|
|
||||||
|
/*
|
||||||
$colors = $wire->sanitizer->pageName($input->post('colors'));
|
$colors = $wire->sanitizer->pageName($input->post('colors'));
|
||||||
if(!in_array($colors, $this->colors)) $colors = reset($this->colors);
|
if(!in_array($colors, $this->colors)) $colors = reset($this->colors);
|
||||||
$theme = $wire->modules->getInstall('AdminThemeDefault');
|
$theme = $wire->modules->getInstall('AdminThemeDefault');
|
||||||
@@ -1119,20 +1197,28 @@ class Installer {
|
|||||||
$configData['colors'] = $colors;
|
$configData['colors'] = $colors;
|
||||||
$wire->modules->saveModuleConfigData('AdminThemeDefault', $configData);
|
$wire->modules->saveModuleConfigData('AdminThemeDefault', $configData);
|
||||||
$this->ok("Saved admin color set <b>$colors</b> - you will see this when you login.");
|
$this->ok("Saved admin color set <b>$colors</b> - you will see this when you login.");
|
||||||
|
*/
|
||||||
|
$this->sectionStop();
|
||||||
|
|
||||||
$this->h("Complete & Secure Your Installation");
|
$this->sectionStart("fa-life-buoy Complete & Secure Your Installation");
|
||||||
$this->getRemoveableItems($wire, false, true);
|
$this->getRemoveableItems($wire, false, true);
|
||||||
|
|
||||||
$this->ok("Note that future runtime errors are logged to <b>/site/assets/logs/errors.txt</b> (not web accessible).");
|
$this->ok("Note that future runtime errors are logged to <b>/site/assets/logs/errors.txt</b> (not web accessible).");
|
||||||
$this->ok("For more configuration options see <b>/wire/config.php</b>.");
|
$this->ok("For more configuration options see <b>/wire/config.php</b> and place any edits in /site/config.php.");
|
||||||
$this->warn("Please make your <b>/site/config.php</b> file non-writable, and readable only to you and Apache.");
|
$this->p(
|
||||||
$this->p("<a target='_blank' href='https://processwire.com/docs/security/file-permissions/#securing-your-site-config.php-file'>How to secure your /site/config.php file <i class='fa fa-angle-right'></i></a>");
|
"Please make your <b>/site/config.php</b> file non-writable, and readable only to you and Apache.<br />" .
|
||||||
|
"<a target='_blank' href='https://processwire.com/docs/security/file-permissions/#securing-your-site-config.php-file'>" .
|
||||||
|
"How to secure your /site/config.php file <i class='fa fa-angle-right'></i></a>"
|
||||||
|
);
|
||||||
|
$this->sectionStop();
|
||||||
|
|
||||||
if(is_writable("./site/modules/")) wireChmod("./site/modules/", true);
|
if(is_writable("./site/modules/")) wireChmod("./site/modules/", true);
|
||||||
|
|
||||||
$this->h("Use The Site!");
|
$this->sectionStart("fa-coffee Use The Site!");
|
||||||
$this->ok("Your admin URL is <a href='./$adminName/'>/$adminName/</a>");
|
$this->ok("Your admin URL is <a href='./$adminName/'>/$adminName/</a>");
|
||||||
$this->p("If you'd like, you may change this later by editing the admin page and changing the name.", "detail");
|
$this->p("If you'd like, you may change this later by editing the admin page and changing the name.", "detail");
|
||||||
|
$this->sectionStop();
|
||||||
|
|
||||||
$this->btn("Login to Admin", 1, 'sign-in', false, true, "./$adminName/");
|
$this->btn("Login to Admin", 1, 'sign-in', false, true, "./$adminName/");
|
||||||
$this->btn("View Site ", 1, 'angle-right', true, false, "./");
|
$this->btn("View Site ", 1, 'angle-right', true, false, "./");
|
||||||
|
|
||||||
@@ -1148,6 +1234,44 @@ class Installer {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function alertOk($str) {
|
||||||
|
if($this->inSection) {
|
||||||
|
$this->ok($str);
|
||||||
|
} else {
|
||||||
|
echo "\n<div class='uk-alert uk-alert-primary'><i class='fa fa-fw fa-check'></i> $str</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function alertWarn($str) {
|
||||||
|
if($this->inSection) {
|
||||||
|
$this->warn($str);
|
||||||
|
} else {
|
||||||
|
$this->numErrors++;
|
||||||
|
echo "\n<div class='uk-alert uk-alert-warning'><i class='fa fa-fw fa-exclamation-triangle'></i> $str</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function alertErr($str) {
|
||||||
|
if($this->inSection) {
|
||||||
|
$this->err($str);
|
||||||
|
} else {
|
||||||
|
$this->numErrors++;
|
||||||
|
echo "\n<div class='uk-alert uk-alert-danger'><i class='fa fa-fw fa-exclamation-triangle'></i> $str</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report and log an error
|
* Report and log an error
|
||||||
*
|
*
|
||||||
@@ -1156,8 +1280,13 @@ class Installer {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function err($str) {
|
protected function err($str) {
|
||||||
|
if(!$this->inSection) {
|
||||||
|
$this->alertErr($str);
|
||||||
|
} else {
|
||||||
$this->numErrors++;
|
$this->numErrors++;
|
||||||
echo "\n<li class='ui-state-error'><i class='fa fa-exclamation-triangle'></i> $str</li>";
|
//echo "\n<li class='ui-state-error'><i class='fa fa-exclamation-triangle'></i> $str</li>";
|
||||||
|
echo "\n<div class='uk-text-danger'><i class='fa fa-fw fa-exclamation-triangle'></i> $str</div>";
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1169,8 +1298,13 @@ class Installer {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function warn($str) {
|
protected function warn($str) {
|
||||||
|
if(!$this->inSection) {
|
||||||
|
$this->alertWarn($str);
|
||||||
|
} else {
|
||||||
$this->numErrors++;
|
$this->numErrors++;
|
||||||
echo "\n<li class='ui-state-error ui-priority-secondary'><i class='fa fa-asterisk'></i> $str</li>";
|
//echo "\n<li class='ui-state-error ui-priority-secondary'><i class='fa fa-asterisk'></i> $str</li>";
|
||||||
|
echo "\n<div class='uk-text-danger'><i class='fa fa-fw fa-asterisk'></i> $str</div>";
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1182,7 +1316,12 @@ class Installer {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function ok($str) {
|
protected function ok($str) {
|
||||||
echo "\n<li class='ui-state-highlight'><i class='fa fa-check-square-o'></i> $str</li>";
|
if(!$this->inSection) {
|
||||||
|
$this->alertOk($str);
|
||||||
|
} else {
|
||||||
|
//echo "\n<li class='ui-state-highlight'><i class='fa fa-check-square-o'></i> $str</li>";
|
||||||
|
echo "\n<div class=''><i class='fa fa-fw fa-check'></i> $str</div>";
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1199,7 +1338,7 @@ class Installer {
|
|||||||
*/
|
*/
|
||||||
protected function btn($label, $value, $icon = 'angle-right', $secondary = false, $float = false, $href = '') {
|
protected function btn($label, $value, $icon = 'angle-right', $secondary = false, $float = false, $href = '') {
|
||||||
$class = $secondary ? 'ui-priority-secondary' : '';
|
$class = $secondary ? 'ui-priority-secondary' : '';
|
||||||
if($float) $class .= " floated";
|
if($float) $class .= " uk-float-left";
|
||||||
$type = 'submit';
|
$type = 'submit';
|
||||||
if($href) $type = 'button';
|
if($href) $type = 'button';
|
||||||
if($href) echo "<a href='$href'>";
|
if($href) echo "<a href='$href'>";
|
||||||
@@ -1214,22 +1353,40 @@ class Installer {
|
|||||||
* Output a headline
|
* Output a headline
|
||||||
*
|
*
|
||||||
* @param string $label
|
* @param string $label
|
||||||
|
* @param string $icon
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function h($label) {
|
protected function h($label, $icon = '') {
|
||||||
echo "\n<h2>$label</h2>";
|
if(strpos($label, 'fa-') === 0) {
|
||||||
|
list($icon, $label) = explode(' ', $label, 2);
|
||||||
|
}
|
||||||
|
if($icon) {
|
||||||
|
if(strpos($icon, 'fa-') !== 0) $icon = "fa-$icon";
|
||||||
|
$icon = "<i class='fa fa-fw $icon'></i> ";
|
||||||
|
}
|
||||||
|
echo "\n<h2>$icon$label</h2>";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output a paragraph
|
* Output a paragraph
|
||||||
*
|
*
|
||||||
* @param string $text
|
* @param string $text
|
||||||
* @param string $class
|
* @param string|array $class Class name, or array of attributes
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function p($text, $class = '') {
|
protected function p($text, $class = '') {
|
||||||
if($class) echo "\n<p class='$class'>$text</p>";
|
$icon = '';
|
||||||
else echo "\n<p>$text</p>";
|
if(strpos($text, 'fa-') === 0) list($icon, $text) = explode(' ', $text, 2);
|
||||||
|
if($icon) $icon = "<i class='fa fa-fw $icon'></i> ";
|
||||||
|
if(is_array($class)) {
|
||||||
|
echo "\n<p";
|
||||||
|
foreach($class as $k => $v) echo " $k='$v'";
|
||||||
|
echo ">$icon$text</p>";
|
||||||
|
} else if($class) {
|
||||||
|
echo "\n<p class='$class'>$icon$text</p>";
|
||||||
|
} else {
|
||||||
|
echo "\n<p>$icon$text</p>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1244,7 +1401,7 @@ class Installer {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function input($name, $label, $value, $clear = false, $type = "text", $required = true) {
|
protected function input($name, $label, $value, $clear = false, $type = "text", $required = true) {
|
||||||
$width = 135;
|
$width = 150;
|
||||||
$required = $required ? "required='required'" : "";
|
$required = $required ? "required='required'" : "";
|
||||||
$pattern = '';
|
$pattern = '';
|
||||||
$note = '';
|
$note = '';
|
||||||
@@ -1255,12 +1412,91 @@ class Installer {
|
|||||||
$type = 'text';
|
$type = 'text';
|
||||||
$pattern = "pattern='[-_a-z0-9]{2,50}' ";
|
$pattern = "pattern='[-_a-z0-9]{2,50}' ";
|
||||||
if($name == 'admin_name') $width = ($width*2);
|
if($name == 'admin_name') $width = ($width*2);
|
||||||
$note = "<small class='detail' style='font-weight: normal;'>(a-z 0-9)</small>";
|
//$note = "<small class='detail' style='font-weight: normal;'>(a-z 0-9)</small>";
|
||||||
|
$note = "<span class='uk-text-small uk-text-muted'>(a-z 0-9)</span>";
|
||||||
}
|
}
|
||||||
$inputWidth = $width - 15;
|
$inputWidth = $width - 15;
|
||||||
$value = htmlentities($value, ENT_QUOTES, "UTF-8");
|
$value = htmlentities($value, ENT_QUOTES, "UTF-8");
|
||||||
echo "\n<p style='width: {$width}px; float: left; margin-top: 0;'><label>$label $note<br /><input type='$type' name='$name' value='$value' $required $pattern style='width: {$inputWidth}px;' /></label></p>";
|
echo "\n<p style='width: {$width}px; float: left; margin-top: 0;'><label>$label $note<br />";
|
||||||
if($clear) echo "\n<br style='clear: both;' />";
|
echo "<input class='uk-input' type='$type' name='$name' value='$value' $required $pattern style='width: {$inputWidth}px;' /></label></p>";
|
||||||
|
if($clear) $this->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output a <select>
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $label
|
||||||
|
* @param string $value
|
||||||
|
* @param array $options
|
||||||
|
* @param int $width
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function select($name, $label, $value, array $options, $width = 150) {
|
||||||
|
|
||||||
|
if($width) {
|
||||||
|
$inputWidth = $width - 15;
|
||||||
|
$inputStyle = " style='width: {$inputWidth}px'";
|
||||||
|
echo "\n<p style='width: {$width}px; float: left; margin-top: 0;'>";
|
||||||
|
} else {
|
||||||
|
$inputStyle = '';
|
||||||
|
echo "\n<p style='margin-top:0'>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if($label) echo "<label>$label</label><br />";
|
||||||
|
echo "\n\t<select class='uk-select' name='$name'$inputStyle>";
|
||||||
|
|
||||||
|
foreach($options as $k => $v) {
|
||||||
|
if(is_int($k)) $k = $v; // make non-assoc array behave same as assoc
|
||||||
|
$selected = $k === $value ? " selected='selected'" : "";
|
||||||
|
echo "\n\t\t<option value='$k'$selected>$v</option>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n\t</select>";
|
||||||
|
echo "\n</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function selectTimezone($value) {
|
||||||
|
echo "\n<p style='width:240px'>";
|
||||||
|
echo "\n\t<select class='uk-select' name='timezone'>";
|
||||||
|
foreach($this->timezones() as $key => $timezone) {
|
||||||
|
$label = $timezone;
|
||||||
|
if(strpos($label, '|')) list($label, $timezone) = explode('|', $label);
|
||||||
|
$selected = $timezone == $value ? "selected='selected'" : '';
|
||||||
|
$label = str_replace('_', ' ', $label);
|
||||||
|
echo "\n\t\t<option value=\"$key\" $selected>$label</option>";
|
||||||
|
}
|
||||||
|
echo "\n\t</select>\n</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function textarea($name, $label, $value, $rows = 0) {
|
||||||
|
$rows = $rows ? " rows='$rows'" : "";
|
||||||
|
$value = htmlentities($value, ENT_QUOTES, 'UTF-8');
|
||||||
|
echo "\n<p>";
|
||||||
|
if($label) echo "\n\t<label for='textarea_$name'>$label</label><br />";
|
||||||
|
echo "\n\t<textarea class='uk-textarea' id='textarea_$name' name='$name'$rows style='width: 100%;'>$value</textarea>";
|
||||||
|
echo "\n</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function sectionStart($headline = '', $type = 'muted') {
|
||||||
|
echo "\n<div class='uk-section uk-section-small uk-section-$type uk-padding uk-margin'>";
|
||||||
|
echo "\n\t<div class='uk-container'>";
|
||||||
|
$icon = '';
|
||||||
|
if(strpos($headline, 'fa-') === 0) {
|
||||||
|
list($icon, $headline) = explode(' ', $headline, 2);
|
||||||
|
$icon = "<i class='fa fa-fw $icon'></i> ";
|
||||||
|
}
|
||||||
|
if($headline) echo "<h2>$icon$headline</h2>";
|
||||||
|
$this->inSection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function sectionStop() {
|
||||||
|
echo "\n\t</div>\n</div>";
|
||||||
|
$this->inSection = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function clear() {
|
||||||
|
echo "\n<div style='clear: both;'></div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1281,10 +1517,10 @@ class Installer {
|
|||||||
if(self::TEST_MODE) return true;
|
if(self::TEST_MODE) return true;
|
||||||
if(is_dir($path) || mkdir($path)) {
|
if(is_dir($path) || mkdir($path)) {
|
||||||
chmod($path, octdec($this->chmodDir));
|
chmod($path, octdec($this->chmodDir));
|
||||||
if($showNote) $this->ok("Created directory: $path");
|
if($showNote) $this->alertOk("Created directory: $path");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if($showNote) $this->err("Error creating directory: $path");
|
if($showNote) $this->alertErr("Error creating directory: $path");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,11 +9,9 @@ if(!defined("PROCESSWIRE_INSTALL")) die();
|
|||||||
|
|
||||||
<!-- FOOTER -->
|
<!-- FOOTER -->
|
||||||
<footer id='pw-footer' class='uk-margin'>
|
<footer id='pw-footer' class='uk-margin'>
|
||||||
<div class='pw-container uk-container uk-container-expand'>
|
<div class='pw-container uk-container uk-container-center'>
|
||||||
<div class='uk-text-center'>
|
|
||||||
<p>ProcessWire 3.x © 2017</p>
|
<p>ProcessWire 3.x © 2017</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@@ -29,6 +29,11 @@ $formAction = htmlentities($formAction, ENT_QUOTES, "UTF-8");
|
|||||||
input, select, textarea {
|
input, select, textarea {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
#main,
|
||||||
|
#pw-mastheads .uk-container,
|
||||||
|
#pw-footer .uk-container {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script type='text/javascript' src='wire/modules/Jquery/JqueryCore/JqueryCore.js'></script>
|
<script type='text/javascript' src='wire/modules/Jquery/JqueryCore/JqueryCore.js'></script>
|
||||||
@@ -43,7 +48,7 @@ $formAction = htmlentities($formAction, ENT_QUOTES, "UTF-8");
|
|||||||
|
|
||||||
<div id='pw-mastheads'>
|
<div id='pw-mastheads'>
|
||||||
<header id='pw-masthead-mobile' class='pw-masthead uk-background-muted'>
|
<header id='pw-masthead-mobile' class='pw-masthead uk-background-muted'>
|
||||||
<div class='pw-container uk-container uk-container-expand uk-text-center'>
|
<div class='pw-container uk-container uk-container-center'>
|
||||||
<a href='https://processwire.com' target='_blank' class='pw-logo-link'>
|
<a href='https://processwire.com' target='_blank' class='pw-logo-link'>
|
||||||
<img class='pw-logo pw-logo-native' src='wire/modules/AdminTheme/AdminThemeUikit/uikit/custom/images/pw-mark.png' alt='' />
|
<img class='pw-logo pw-logo-native' src='wire/modules/AdminTheme/AdminThemeUikit/uikit/custom/images/pw-mark.png' alt='' />
|
||||||
</a>
|
</a>
|
||||||
@@ -53,7 +58,7 @@ $formAction = htmlentities($formAction, ENT_QUOTES, "UTF-8");
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- MAIN CONTENT -->
|
<!-- MAIN CONTENT -->
|
||||||
<main id='main' class='pw-container uk-container uk-container-expand uk-margin uk-margin-large-bottom'>
|
<main id='main' class='pw-container uk-container uk-container-center uk-margin'>
|
||||||
<div class='pw-content' id='content'>
|
<div class='pw-content' id='content'>
|
||||||
<header id='pw-content-head'>
|
<header id='pw-content-head'>
|
||||||
<h1 class='uk-margin-remove-top'><?php echo $title; ?></h1>
|
<h1 class='uk-margin-remove-top'><?php echo $title; ?></h1>
|
||||||
|
Reference in New Issue
Block a user