Ivan - Fix Installation issues [skip ci]

This commit is contained in:
ivan 2017-03-29 18:46:26 -03:00
parent 3047831864
commit 48614fcc00
33 changed files with 223 additions and 107 deletions

View File

@ -2,6 +2,16 @@ import API from 'lib-app/api-call';
import sessionStore from 'lib-app/session-store'; import sessionStore from 'lib-app/session-store';
export default { export default {
checkInstallation() {
return {
type: 'CHECK_INSTALLATION',
payload: API.call({
path: '/system/installation-done',
data: {}
})
};
},
init() { init() {
if (sessionStore.isLoggedIn()) { if (sessionStore.isLoggedIn()) {
return { return {

View File

@ -74,7 +74,7 @@ class App extends React.Component {
} }
if (validations.languageChanged) { if (validations.languageChanged) {
browserHistory.push(props.location.pathname); window.location.reload();
} }
if (validations.loggedOut) { if (validations.loggedOut) {
@ -99,7 +99,7 @@ class App extends React.Component {
browserHistory.push('/'); browserHistory.push('/');
} }
if(!props.config['user-system-enabled'] && _.includes(props.location.pathname, '/check-ticket')) { if(props.config['user-system-enabled'] && _.includes(props.location.pathname, '/check-ticket')) {
browserHistory.push('/'); browserHistory.push('/');
} }
} }

View File

@ -122,7 +122,7 @@ class AdminPanelEmailTemplates extends React.Component {
getItems() { getItems() {
return this.state.items.map((item) => { return this.state.items.map((item) => {
return { return {
content: i18n(item.type) content: item.type
}; };
}); });
} }

View File

@ -174,8 +174,8 @@ class AdminPanelSystemPreferences extends React.Component {
'smtp-port': form['smtp-port'], 'smtp-port': form['smtp-port'],
'smtp-user': form['smtp-user'], 'smtp-user': form['smtp-user'],
'smtp-pass': form['smtp-pass'], 'smtp-pass': form['smtp-pass'],
'maintenance-mode': form['maintenance-mode'], 'maintenance-mode': form['maintenance-mode'] * 1,
'allow-attachments': form['allow-attachments'], 'allow-attachments': form['allow-attachments'] * 1,
'max-size': form['max-size'], 'max-size': form['max-size'],
'allowedLanguages': JSON.stringify(form.allowedLanguages.map(index => languageKeys[index])), 'allowedLanguages': JSON.stringify(form.allowedLanguages.map(index => languageKeys[index])),
'supportedLanguages': JSON.stringify(form.supportedLanguages.map(index => languageKeys[index])) 'supportedLanguages': JSON.stringify(form.supportedLanguages.map(index => languageKeys[index]))

View File

@ -62,10 +62,16 @@ class AdminPanelDepartments extends React.Component {
<div className="admin-panel-departments__discard-button"> <div className="admin-panel-departments__discard-button">
<Button onClick={this.onDiscardChangesClick.bind(this)} size="medium">{i18n('DISCARD_CHANGES')}</Button> <Button onClick={this.onDiscardChangesClick.bind(this)} size="medium">{i18n('DISCARD_CHANGES')}</Button>
</div> </div>
{this.props.departments.length > 1 ? this.renderDeleteButton() : null}
</div>
);
}
renderDeleteButton() {
return (
<div className="admin-panel-departments__delete-button"> <div className="admin-panel-departments__delete-button">
<Button onClick={this.onDeleteClick.bind(this)} size="medium">{i18n('DELETE')}</Button> <Button onClick={this.onDeleteClick.bind(this)} size="medium">{i18n('DELETE')}</Button>
</div> </div>
</div>
); );
} }

View File

@ -37,11 +37,16 @@ class InstallStep2Requirements extends React.Component {
</Button> </Button>
</div> </div>
<Table {...this.getTableProps()} /> <Table {...this.getTableProps()} />
<div className="install-step-2__buttons">
<div className="install-step-2__next"> <div className="install-step-2__next">
<Button disabled={!this.isAllOk()} size="medium" type="secondary" onClick={() => browserHistory.push('/install/step-3')}> <Button disabled={!this.isAllOk()} size="medium" type="secondary" onClick={() => browserHistory.push('/install/step-3')}>
{i18n('NEXT')} {i18n('NEXT')}
</Button> </Button>
</div> </div>
<div className="install-step-2__previous">
<Button size="medium" onClick={this.onPreviousClick.bind(this)}>{i18n('PREVIOUS')}</Button>
</div>
</div>
</div> </div>
); );
} }
@ -83,6 +88,11 @@ class InstallStep2Requirements extends React.Component {
return classNames(classes); return classNames(classes);
} }
onPreviousClick(event) {
event.preventDefault();
browserHistory.push('/install/step-1');
}
isAllOk() { isAllOk() {
return _.every(this.state.requirements, {ok: true}); return _.every(this.state.requirements, {ok: true});
} }

View File

@ -25,13 +25,10 @@
&__requirement { &__requirement {
color: $secondary-blue; color: $secondary-blue;
&-value {
width: 200px;
}
&-assert { &-assert {
color: $primary-green; color: $primary-green;
float: right; float: left;
margin-right: 11px;
margin-top: 3px; margin-top: 3px;
} }
@ -45,7 +42,13 @@
} }
} }
&__next { &__previous {
float: left;
}
&__next {
float: left;
position: absolute;
margin-left: 103px;
} }
} }

View File

@ -26,9 +26,9 @@ class InstallStep3Database extends React.Component {
{this.renderMessage()} {this.renderMessage()}
<Form loading={this.state.loading} onSubmit={this.onSubmit.bind(this)}> <Form loading={this.state.loading} onSubmit={this.onSubmit.bind(this)}>
<FormField name="dbHost" label={i18n('DATABASE_HOST')} fieldProps={{size: 'large'}} required/> <FormField name="dbHost" label={i18n('DATABASE_HOST')} fieldProps={{size: 'large'}} required/>
<FormField name="dbName" label={i18n('DATABASE_NAME')} fieldProps={{size: 'large'}} required/> <FormField name="dbName" label={i18n('DATABASE_NAME')} fieldProps={{size: 'large'}} infoMessage={i18n('LEFT_EMPTY_DATABASE')}/>
<FormField name="dbUser" label={i18n('DATABASE_USER')} fieldProps={{size: 'large'}} required/> <FormField name="dbUser" label={i18n('DATABASE_USER')} fieldProps={{size: 'large'}} required/>
<FormField name="dbPassword" label={i18n('DATABASE_PASSWORD')} fieldProps={{size: 'large', password: true}} required/> <FormField name="dbPassword" label={i18n('DATABASE_PASSWORD')} fieldProps={{size: 'large', password: true}}/>
<div className="install-step-3__buttons"> <div className="install-step-3__buttons">
<SubmitButton className="install-step-3__next" size="medium" type="secondary">{i18n('NEXT')}</SubmitButton> <SubmitButton className="install-step-3__next" size="medium" type="secondary">{i18n('NEXT')}</SubmitButton>
<Button className="install-step-3__previous" size="medium" onClick={this.onPreviousClick.bind(this)}>{i18n('PREVIOUS')}</Button> <Button className="install-step-3__previous" size="medium" onClick={this.onPreviousClick.bind(this)}>{i18n('PREVIOUS')}</Button>

View File

@ -15,6 +15,7 @@ import SubmitButton from 'core-components/submit-button';
class InstallStep4UserSystem extends React.Component { class InstallStep4UserSystem extends React.Component {
state = { state = {
loading: false,
form: { form: {
'user-system-enabled': true, 'user-system-enabled': true,
'registration': true 'registration': true
@ -25,7 +26,7 @@ class InstallStep4UserSystem extends React.Component {
return ( return (
<div className="install-step-4"> <div className="install-step-4">
<Header title={i18n('STEP_TITLE', {title: i18n('USER_SYSTEM'), current: 4, total: 6})} description={i18n('STEP_4_DESCRIPTION')}/> <Header title={i18n('STEP_TITLE', {title: i18n('USER_SYSTEM'), current: 4, total: 6})} description={i18n('STEP_4_DESCRIPTION')}/>
<Form onSubmit={this.onSubmit.bind(this)} values={this.state.form} onChange={this.onChange.bind(this)}> <Form onSubmit={this.onSubmit.bind(this)} values={this.state.form} onChange={this.onChange.bind(this)} loading={this.state.loading}>
<FormField name="user-system-enabled" label={i18n('ENABLE_USER_SYSTEM')} decorator={ToggleButton}/> <FormField name="user-system-enabled" label={i18n('ENABLE_USER_SYSTEM')} decorator={ToggleButton}/>
<FormField name="registration" label={i18n('ENABLE_USER_REGISTRATION')} decorator={ToggleButton} fieldProps={{disabled: this.isDisabled()}}/> <FormField name="registration" label={i18n('ENABLE_USER_REGISTRATION')} decorator={ToggleButton} fieldProps={{disabled: this.isDisabled()}}/>
<div className="install-step-4__buttons"> <div className="install-step-4__buttons">
@ -52,14 +53,18 @@ class InstallStep4UserSystem extends React.Component {
} }
onSubmit(form) { onSubmit(form) {
API.call({ this.setState({
loading: true
}, () => API.call({
path: '/system/init-settings', path: '/system/init-settings',
data: { data: {
'language': this.props.language, 'language': this.props.language,
'user-system-enabled': form['user-system-enabled'] * 1, 'user-system-enabled': form['user-system-enabled'] * 1,
'registration': form['registration'] * 1 'registration': form['registration'] * 1
} }
}).then(() => browserHistory.push('/install/step-5')); }).then(() => this.setState({
loading: false
}, () => browserHistory.push('/install/step-5'))));
} }
isDisabled() { isDisabled() {

View File

@ -2,7 +2,6 @@ import React from 'react';
import {browserHistory} from 'react-router'; import {browserHistory} from 'react-router';
import i18n from 'lib-app/i18n'; import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import Header from 'core-components/header'; import Header from 'core-components/header';
import Message from 'core-components/message'; import Message from 'core-components/message';

View File

@ -57,13 +57,13 @@ class DashboardListArticlesPage extends React.Component {
); );
} }
renderSearchResultsItem(item) { renderSearchResultsItem(item, index) {
let content = this.stripHTML(item.content); let content = this.stripHTML(item.content);
content = content.substring(0, 100); content = content.substring(0, 100);
content += '...'; content += '...';
return ( return (
<div className="dashboard-list-articles-page__search-result"> <div className="dashboard-list-articles-page__search-result" key={index}>
<div className="dashboard-list-articles-page__search-result-title"> <div className="dashboard-list-articles-page__search-result-title">
<Link to={((this.props.location.pathname == '/articles') ? '/article/' : '/dashboard/article/') + item.id}>{item.title}</Link> <Link to={((this.props.location.pathname == '/articles') ? '/article/' : '/dashboard/article/') + item.id}>{item.title}</Link>
</div> </div>

View File

@ -36,9 +36,9 @@ class ColorSelector extends React.Component {
); );
} }
renderTooltipColor(color) { renderTooltipColor(color, index) {
return ( return (
<span className="color-selector__tooltip-color" onClick={this.onColorClick.bind(this, color)} style={{backgroundColor: color}}/> <span className="color-selector__tooltip-color" onClick={this.onColorClick.bind(this, color)} style={{backgroundColor: color}} key={index}/>
); );
} }

View File

@ -16,7 +16,7 @@ class FormField extends React.Component {
}; };
static propTypes = { static propTypes = {
decorator: React.PropTypes.func, decorator: React.PropTypes.oneOfType(React.PropTypes.func, React.PropTypes.string),
validation: React.PropTypes.string, validation: React.PropTypes.string,
onChange: React.PropTypes.func, onChange: React.PropTypes.func,
onBlur: React.PropTypes.func, onBlur: React.PropTypes.func,

View File

@ -39,9 +39,9 @@ class IconSelector extends React.Component {
); );
} }
renderTooltipIcon(name) { renderTooltipIcon(name, index) {
return ( return (
<div className="icon-selector__tooltip-icon" onClick={this.onIconClick.bind(this, name)}> <div className="icon-selector__tooltip-icon" onClick={this.onIconClick.bind(this, name)} key={index}>
<Icon name={name} /> <Icon name={name} />
</div> </div>
); );

View File

@ -349,5 +349,6 @@ export default {
'ACTIVITY_RE_OPEN_THIS': 'reopened this ticket', 'ACTIVITY_RE_OPEN_THIS': 'reopened this ticket',
'ACTIVITY_DEPARTMENT_CHANGED_THIS': 'changed department of this ticket to ', 'ACTIVITY_DEPARTMENT_CHANGED_THIS': 'changed department of this ticket to ',
'ACTIVITY_PRIORITY_CHANGED_THIS': 'changed priority of this ticket to', 'ACTIVITY_PRIORITY_CHANGED_THIS': 'changed priority of this ticket to',
'DATE_PREFIX': 'on' 'DATE_PREFIX': 'on',
'LEFT_EMPTY_DATABASE': 'Left empty for automatic database creation'
}; };

View File

@ -6,7 +6,7 @@
<meta name="description" content=""> <meta name="description" content="">
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<title>OS4</title> <title>OpenSupports</title>
<link rel="stylesheet" href="/css/main.css"> <link rel="stylesheet" href="/css/main.css">
<link rel="icon" type="image/x-icon" href="/images/icon.png"> <link rel="icon" type="image/x-icon" href="/images/icon.png">
@ -17,6 +17,5 @@
<script src="/js/config.js"></script> <script src="/js/config.js"></script>
<script src="/js/main.js"></script> <script src="/js/main.js"></script>
</body> </body>
</html> </html>

View File

@ -37,5 +37,6 @@ let unsubscribe = store.subscribe(() => {
} }
}); });
store.dispatch(ConfigActions.checkInstallation());
store.dispatch(ConfigActions.init()); store.dispatch(ConfigActions.init());
store.dispatch(SessionActions.initSession()); store.dispatch(SessionActions.initSession());

23
client/src/index.php Normal file
View File

@ -0,0 +1,23 @@
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<title>OpenSupports</title>
<link rel="stylesheet" href="/css/main.css">
<link rel="icon" type="image/x-icon" href="/images/icon.png">
</head>
<body>
<div id="app"></div>
<script>
root = "<?php echo ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']); ?>";
apiRoot = "<?php echo ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']); ?>" + 'api';
</script>
<script src="/js/main.js"></script>
</body>
</html>

View File

@ -69,7 +69,7 @@ class SessionStore {
return { return {
language: this.getItem('language'), language: this.getItem('language'),
reCaptchaKey: this.getItem('reCaptchaKey'), reCaptchaKey: this.getItem('reCaptchaKey'),
departments: this.getDepartments(), departments: this.getDepartments() || [],
allowedLanguages: JSON.parse(this.getItem('allowedLanguages')), allowedLanguages: JSON.parse(this.getItem('allowedLanguages')),
supportedLanguages: JSON.parse(this.getItem('supportedLanguages')), supportedLanguages: JSON.parse(this.getItem('supportedLanguages')),
layout: this.getItem('layout'), layout: this.getItem('layout'),
@ -110,7 +110,7 @@ class SessionStore {
} }
setItem(key, value) { setItem(key, value) {
return this.storage.setItem(key, value); return this.storage.setItem(key, (value !== undefined) ? value : '');
} }
removeItem(key) { removeItem(key) {

View File

@ -8,7 +8,9 @@ class ConfigReducer extends Reducer {
getInitialState() { getInitialState() {
return { return {
language: sessionStore.getItem('language'), language: sessionStore.getItem('language'),
initDone: false initDone: false,
installedDone: false,
installed: false
}; };
} }
@ -16,6 +18,7 @@ class ConfigReducer extends Reducer {
return { return {
'CHANGE_LANGUAGE': this.onLanguageChange, 'CHANGE_LANGUAGE': this.onLanguageChange,
'INIT_CONFIGS_FULFILLED': this.onInitConfigs, 'INIT_CONFIGS_FULFILLED': this.onInitConfigs,
'CHECK_INSTALLATION_FULFILLED': this.onInstallationChecked,
'UPDATE_DATA_FULFILLED': this.onInitConfigs 'UPDATE_DATA_FULFILLED': this.onInitConfigs
}; };
} }
@ -44,6 +47,13 @@ class ConfigReducer extends Reducer {
initDone: true initDone: true
}); });
} }
onInstallationChecked(state, payload) {
return _.extend({}, state, {
installedDone: true,
installed: payload.data
});
}
} }
export default ConfigReducer.getInstance(); export default ConfigReducer.getInstance();

View File

@ -57,7 +57,7 @@ class EditStaffController extends Controller {
$this->staffInstance->sharedDepartmentList = $this->getDepartmentList(); $this->staffInstance->sharedDepartmentList = $this->getDepartmentList();
} }
if($fileUploader = $this->uploadFile()) { if($fileUploader = $this->uploadFile(true)) {
$this->staffInstance->profilePic = ($fileUploader instanceof FileUploader) ? $fileUploader->getFileName() : null; $this->staffInstance->profilePic = ($fileUploader instanceof FileUploader) ? $fileUploader->getFileName() : null;
} }

View File

@ -18,6 +18,13 @@ class GetAllTicketsStaffController extends Controller {
} }
public function handler() { public function handler() {
if (Ticket::isTableEmpty()) {
Response::respondSuccess([
'tickets' => [],
'pages' => 0
]);
return;
}
Response::respondSuccess([ Response::respondSuccess([
'tickets' => $this->getTicketList()->toArray(), 'tickets' => $this->getTicketList()->toArray(),

View File

@ -13,6 +13,11 @@ class GetNewTicketsStaffController extends Controller {
]; ];
} }
public function handler() { public function handler() {
if (Ticket::isTableEmpty()) {
Response::respondSuccess([]);
return;
}
$user = Controller::getLoggedUser(); $user = Controller::getLoggedUser();
$query = ' ('; $query = ' (';
foreach ($user->sharedDepartmentList as $department) { foreach ($user->sharedDepartmentList as $department) {

View File

@ -14,6 +14,8 @@ class CheckRequirementsController extends Controller {
} }
public function handler() { public function handler() {
$configWritable = !!fopen('config.php', 'w+');
Response::respondSuccess([ Response::respondSuccess([
'phpVersion' => [ 'phpVersion' => [
'name' => 'PHP Version', 'name' => 'PHP Version',
@ -32,8 +34,8 @@ class CheckRequirementsController extends Controller {
], ],
'files' => [ 'files' => [
'name' => 'Folder: /api/files', 'name' => 'Folder: /api/files',
'value' => is_writable('files/') ? 'Writable' : 'Not writable', 'value' => $configWritable ? 'Writable' : 'Not writable',
'ok' => is_writable('files/') 'ok' => $configWritable
] ]
]); ]);
} }

View File

@ -12,16 +12,18 @@ class GetSettingsController extends Controller {
} }
public function handler() { public function handler() {
$settingsList = [];
if(InstallationDoneController::isInstallationDone()) {
if(Controller::request('allSettings') && Controller::isStaffLogged(3)) { if(Controller::request('allSettings') && Controller::isStaffLogged(3)) {
$settingsList = [ $settingsList = [
'language' => Setting::getSetting('language')->getValue(), 'language' => Setting::getSetting('language')->getValue(),
'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(), 'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(),
'reCaptchaPrivate' => Setting::getSetting('recaptcha-private')->getValue(), 'reCaptchaPrivate' => Setting::getSetting('recaptcha-private')->getValue(),
'time-zone' => Setting::getSetting('time-zone')->getValue(), 'time-zone' => Setting::getSetting('time-zone')->getValue(),
'maintenance-mode' => Setting::getSetting('maintenance-mode')->getValue(), 'maintenance-mode' => Setting::getSetting('maintenance-mode')->getValue() * 1,
'layout' => Setting::getSetting('layout')->getValue(), 'layout' => Setting::getSetting('layout')->getValue(),
'allow-attachments' => Setting::getSetting('allow-attachments')->getValue(), 'allow-attachments' => Setting::getSetting('allow-attachments')->getValue() * 1,
'max-size' => Setting::getSetting('max-size')->getValue(), 'max-size' => Setting::getSetting('max-size')->getValue(),
'url' => Setting::getSetting('url')->getValue(), 'url' => Setting::getSetting('url')->getValue(),
'title' => Setting::getSetting('title')->getValue(), 'title' => Setting::getSetting('title')->getValue(),
@ -39,18 +41,19 @@ class GetSettingsController extends Controller {
'language' => Setting::getSetting('language')->getValue(), 'language' => Setting::getSetting('language')->getValue(),
'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(), 'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(),
'time-zone' => Setting::getSetting('time-zone')->getValue(), 'time-zone' => Setting::getSetting('time-zone')->getValue(),
'maintenance-mode' => Setting::getSetting('maintenance-mode')->getValue(), 'maintenance-mode' => Setting::getSetting('maintenance-mode')->getValue() * 1,
'layout' => Setting::getSetting('layout')->getValue(), 'layout' => Setting::getSetting('layout')->getValue(),
'allow-attachments' => Setting::getSetting('allow-attachments')->getValue(), 'allow-attachments' => Setting::getSetting('allow-attachments')->getValue() * 1,
'max-size' => Setting::getSetting('max-size')->getValue(), 'max-size' => Setting::getSetting('max-size')->getValue(),
'title' => Setting::getSetting('title')->getValue(), 'title' => Setting::getSetting('title')->getValue(),
'registration' => Setting::getSetting('registration')->getValue(), 'registration' => Setting::getSetting('registration')->getValue(),
'departments' => Department::getDepartmentNames(), 'departments' => Department::getDepartmentNames(),
'supportedLanguages' => Language::getSupportedLanguages(), 'supportedLanguages' => Language::getSupportedLanguages(),
'allowedLanguages' => Language::getAllowedLanguages(), 'allowedLanguages' => Language::getAllowedLanguages(),
'user-system-enabled' => Setting::getSetting('user-system-enabled')->getValue() 'user-system-enabled' => Setting::getSetting('user-system-enabled')->getValue() * 1
]; ];
} }
}
Response::respondSuccess($settingsList); Response::respondSuccess($settingsList);
} }

View File

@ -14,17 +14,43 @@ class InitDatabaseController extends Controller {
} }
public function handler() { public function handler() {
if(defined('MYSQL_HOST')) { if(InstallationDoneController::isInstallationDone()) {
throw new Exception(ERRORS::INIT_SETTINGS_DONE); throw new Exception(ERRORS::INIT_SETTINGS_DONE);
return; }
$dbHost = Controller::request('dbHost');
$dbName = Controller::request('dbName');
$dbUser = Controller::request('dbUser');
$dbPass = Controller::request('dbPassword');
if(!defined('MYSQL_HOST')) {
RedBean::setup('mysql:host=' . $dbHost, $dbUser, $dbPass);
}
if($dbName) {
RedBean::addDatabase($dbName, 'mysql:host='. $dbHost . ';dbname=' . $dbName, $dbUser, $dbPass);
RedBean::selectDatabase($dbName);
if(!RedBean::testConnection()) {
throw new Exception(ERRORS::DATABASE_CONNECTION);
}
} else {
$dbName = 'opensupports_' . Hashing::generateRandomNumber(100, 999);
RedBean::exec('CREATE DATABASE ' . $dbName);
RedBean::addDatabase($dbName, 'mysql:host='. $dbHost . ';dbname=' . $dbName, $dbUser, $dbPass);
RedBean::selectDatabase($dbName);
if(!RedBean::testConnection()) {
throw new Exception(ERRORS::DATABASE_CREATION);
}
} }
$configFile = fopen('config.php', 'w+') or die(ERRORS::INVALID_FILE); $configFile = fopen('config.php', 'w+') or die(ERRORS::INVALID_FILE);
$content = '<?php' . PHP_EOL; $content = '<?php' . PHP_EOL;
$content .= 'define(\'MYSQL_HOST\', \'' . Controller::request('dbHost') . '\');' . PHP_EOL; $content .= 'define(\'MYSQL_HOST\', \'' . $dbHost . '\');' . PHP_EOL;
$content .= 'define(\'MYSQL_USER\', \'' . Controller::request('dbUser') . '\');' . PHP_EOL; $content .= 'define(\'MYSQL_USER\', \'' . $dbUser . '\');' . PHP_EOL;
$content .= 'define(\'MYSQL_PASSWORD\', \'' . Controller::request('dbPassword') . '\');' . PHP_EOL; $content .= 'define(\'MYSQL_PASSWORD\', \'' . $dbPass . '\');' . PHP_EOL;
$content .= 'define(\'MYSQL_DATABASE\', \'' . Controller::request('dbName') . '\');' . PHP_EOL; $content .= 'define(\'MYSQL_DATABASE\', \'' . $dbName . '\');' . PHP_EOL;
fwrite($configFile, $content); fwrite($configFile, $content);
fclose($configFile); fclose($configFile);

View File

@ -51,9 +51,9 @@ class InitSettingsController extends Controller {
'registration' => !!Controller::request('registration'), 'registration' => !!Controller::request('registration'),
'user-system-enabled' => !!Controller::request('user-system-enabled'), 'user-system-enabled' => !!Controller::request('user-system-enabled'),
'last-stat-day' => date('YmdHi', strtotime(' -12 day ')), 'last-stat-day' => date('YmdHi', strtotime(' -12 day ')),
'ticket-gap' => Hashing::generateRandomPrime(100000, 999999), 'ticket-gap' => Hashing::generateRandomPrime(1000000, 9999999),
'file-gap' => Hashing::generateRandomPrime(100000, 999999), 'file-gap' => Hashing::generateRandomPrime(1000000, 9999999),
'file-first-number' => Hashing::generateRandomNumber(100000, 999999), 'file-first-number' => Hashing::generateRandomNumber(1000000, 9999999),
'file-quantity' => 0 'file-quantity' => 0
]); ]);
} }

View File

@ -5,6 +5,10 @@ class InstallationDoneController extends Controller {
const PATH = '/installation-done'; const PATH = '/installation-done';
const METHOD = 'POST'; const METHOD = 'POST';
public static function isInstallationDone() {
return RedBean::testConnection() && !Setting::isTableEmpty() && !Staff::isTableEmpty();
}
public function validations() { public function validations() {
return [ return [
'permission' => 'any', 'permission' => 'any',
@ -13,7 +17,7 @@ class InstallationDoneController extends Controller {
} }
public function handler() { public function handler() {
if(RedBean::testConnection() && !Setting::isTableEmpty() && !Staff::isTableEmpty()) { if(InstallationDoneController::isInstallationDone()) {
Response::respondSuccess(1); Response::respondSuccess(1);
} else { } else {
Response::respondSuccess(0); Response::respondSuccess(0);

View File

@ -99,8 +99,8 @@ class CommentController extends Controller {
$mailSender = new MailSender(); $mailSender = new MailSender();
$mailSender->setTemplate(MailTemplate::TICKET_RESPONDED, [ $mailSender->setTemplate(MailTemplate::TICKET_RESPONDED, [
'to' => $this->ticket->author->email, 'to' => ($this->ticket->author) ? $this->ticket->author->email : $this->ticket->authorEmail,
'name' => $this->ticket->author->name, 'name' => ($this->ticket->author) ? $this->ticket->author->name : $this->ticket->authorName,
'ticketNumber' => $this->ticket->ticketNumber, 'ticketNumber' => $this->ticket->ticketNumber,
'title' => $this->ticket->title, 'title' => $this->ticket->title,
'url' => Setting::getSetting('url')->getValue() 'url' => Setting::getSetting('url')->getValue()

View File

@ -41,4 +41,6 @@ class ERRORS {
const INVALID_PERIOD = 'INVALID_PERIOD'; const INVALID_PERIOD = 'INVALID_PERIOD';
const NAME_ALREADY_USED = 'NAME_ALREADY_USED'; const NAME_ALREADY_USED = 'NAME_ALREADY_USED';
const INVALID_FILE = 'INVALID_FILE'; const INVALID_FILE = 'INVALID_FILE';
const DATABASE_CONNECTION = 'DATABASE_CONNECTION';
const DATABASE_CREATION = 'DATABASE_CREATION';
} }

View File

@ -1,5 +1,5 @@
<?php <?php
include 'config.php'; @include 'config.php';
require_once 'vendor/autoload.php'; require_once 'vendor/autoload.php';
// REDBEAN CONFIGURATION // REDBEAN CONFIGURATION

View File

@ -17,7 +17,7 @@ abstract class Controller {
$this->validate(); $this->validate();
$this->handler(); $this->handler();
} catch (\Exception $exception) { } catch (\Exception $exception) {
Response::respondError($exception->getMessage()); Response::respondError($exception->getMessage() . ' on line ' . $exception->getFile() . ':' . $exception->getLine());
return; return;
} }
}; };

View File

@ -60,15 +60,15 @@ class Ticketevent extends DataStore {
} }
public function toArray() { public function toArray() {
$user = ($this->authorUser instanceof User) ? $this->authorUser : $this->authorStaff; $user = ($this->authorStaff) ? $this->authorStaff : $this->authorUser;
return [ return [
'type' => $this->type, 'type' => $this->type,
'ticketNumber' => $this->ticket->ticketNumber, 'ticketNumber' => $this->ticket->ticketNumber,
'author' => [ 'author' => [
'name' => $user->name, 'name' => $user ? $user->name : null,
'staff' => $user instanceOf Staff, 'staff' => $user instanceOf Staff,
'id' => $user->id 'id' => $user ? $user->id : null
] ]
]; ];
} }