diff --git a/app/Http/Controllers/SetupController.php b/app/Http/Controllers/SetupController.php index 8d9e7509..ca8a69ba 100644 --- a/app/Http/Controllers/SetupController.php +++ b/app/Http/Controllers/SetupController.php @@ -18,7 +18,7 @@ class SetupController extends Controller public function welcome() { // already installed - if ($this->checkTablesExist()) { + if (self::checkTablesExist()) { return view('setup.locked'); } else { $config = config('database.connections.mysql'); @@ -40,7 +40,7 @@ class SetupController extends Controller public function doUpdate() { $resource = opendir(database_path('update_scripts')); - $update_script_exist = false; + $updateScriptExist = false; $tips = []; @@ -63,7 +63,7 @@ class SetupController extends Controller } } - $update_script_exist = true; + $updateScriptExist = true; } } closedir($resource); @@ -73,7 +73,7 @@ class SetupController extends Controller Option::set($key, $value); } - if (!$update_script_exist) { + if (!$updateScriptExist) { // if update script is not given Option::set('version', config('app.version')); } @@ -104,7 +104,7 @@ class SetupController extends Controller $user = User::register( $request->input('email'), $request->input('password'), - function ($user) + function ($user) use ($request) { $user->ip = $request->ip(); $user->score = option('user_initial_score'); @@ -121,15 +121,16 @@ class SetupController extends Controller ]); } - protected function createDirectories() + /** + * Check if the given tables exist in current database. + * + * @param array $tables [description] + * @return bool + */ + public static function checkTablesExist($tables = [ + 'users', 'closets', 'players', 'textures', 'options' + ]) { - Utils::checkTextureDirectory(); - } - - protected function checkTablesExist() - { - $tables = ['users', 'closets', 'players', 'textures', 'options']; - foreach ($tables as $table_name) { // prefix will be added automatically if (!Schema::hasTable($table_name)) { @@ -140,6 +141,22 @@ class SetupController extends Controller return true; } + public static function checkTextureDirectory() + { + if (!Storage::disk('storage')->has('textures')) { + // mkdir + if (!Storage::disk('storage')->makeDirectory('textures')) + return false; + } + + return true; + } + + protected function createDirectories() + { + return self::checkTextureDirectory(); + } + /** * {@inheritdoc} */ diff --git a/app/Http/Routes/web.php b/app/Http/Routes/web.php index cbb4df22..d82a53b6 100644 --- a/app/Http/Routes/web.php +++ b/app/Http/Routes/web.php @@ -114,8 +114,8 @@ Route::group(['middleware' => 'admin', 'prefix' => 'admin'], function () }); Route::group(['prefix' => 'update'], function () { - Route::any('/update', 'UpdateController@showUpdatePage'); - Route::get('/update/check', 'UpdateController@checkUpdates'); - Route::any('/update/download', 'UpdateController@download'); + Route::any('', 'UpdateController@showUpdatePage'); + Route::get('/check', 'UpdateController@checkUpdates'); + Route::any('/download', 'UpdateController@download'); }); }); diff --git a/app/Providers/BootServiceProvider.php b/app/Providers/BootServiceProvider.php index 4b3b6d73..cf11d977 100644 --- a/app/Providers/BootServiceProvider.php +++ b/app/Providers/BootServiceProvider.php @@ -9,6 +9,7 @@ use App\Services\Database; use Illuminate\Http\Request; use Illuminate\Support\ServiceProvider; use App\Exceptions\PrettyPageException; +use App\Http\Controllers\SetupController; use App\Services\Repositories\OptionRepository; class BootServiceProvider extends ServiceProvider @@ -22,8 +23,20 @@ class BootServiceProvider extends ServiceProvider { View::addExtension('tpl', 'blade'); - $this->checkFileExists(); - $this->checkDbConnection(); + // check dotenv + if (!file_exists(base_path('.env'))) { + throw new PrettyPageException(trans('setup.file.no-dot-env'), -1); + } + + try { + // check database config + Database::prepareConnection(); + } catch (\Exception $e) { + throw new PrettyPageException( + trans('setup.database.connection-error', ['msg' => $e->getMessage()]), + $e->getCode() + ); + } // skip the installation check when setup or under CLI if (!$request->is('setup') && !$request->is('setup/*') && PHP_SAPI != "cli") { @@ -31,43 +44,16 @@ class BootServiceProvider extends ServiceProvider } } - protected function checkFileExists() - { - if (!file_exists(base_path('.env'))) { - throw new PrettyPageException(trans('setup.file.no-dot-env'), -1); - } - } - - protected function checkDbConnection() - { - $config = config('database.connections.mysql'); - - // use error control to hide shitty connect warnings - @$conn = new \mysqli( - $config['host'], - $config['username'], - $config['password'], - $config['database'], - $config['port'] - ); - - if ($conn->connect_error) - throw new PrettyPageException( - trans('setup.database.connection-error', ['msg' => $conn->connect_error]), - $conn->connect_errno - ); - - return true; - } - protected function checkInstallation() { // redirect to setup wizard - if (!$this->checkTablesExist()) { + if (!SetupController::checkTablesExist()) { return redirect('/setup')->send(); } - Utils::checkTextureDirectory(); + if (!SetupController::checkTextureDirectory()) { + throw new PrettyPageException(trans('setup.file.permission-error'), -1); + } if (version_compare(config('app.version'), option('version', ''), '>')) { return redirect('/setup/update')->send(); @@ -76,20 +62,6 @@ class BootServiceProvider extends ServiceProvider return true; } - public static function checkTablesExist() - { - $tables = ['users', 'closets', 'players', 'textures', 'options']; - - foreach ($tables as $table_name) { - // prefix will be added automatically - if (!Schema::hasTable($table_name)) { - return false; - } - } - - return true; - } - /** * Register any application services. * diff --git a/app/Services/Database.php b/app/Services/Database.php index b35b0b34..156c8e48 100644 --- a/app/Services/Database.php +++ b/app/Services/Database.php @@ -2,6 +2,10 @@ namespace App\Services; +use Exception; +use Illuminate\Support\Arr; +use InvalidArgumentException; + /** * Light-weight database helper * @@ -10,69 +14,94 @@ namespace App\Services; class Database { /** - * Instance of MySQLi + * Instance of MySQLi. * * @var null */ private $connection = null; /** - * Connection config + * Database name. * * @var array */ - private $config = null; + private $database = ""; /** - * Table name to do operations in + * Name of table to do operations in. * * @var string */ - private $table_name = ""; + private $tableName = ""; /** - * Construct with table name and another config optionally + * Construct with a config array. * - * @param string $table_name * @param array $config */ public function __construct($config = null) { - $this->config = is_null($config) ? config('database.connections.mysql') : $config; - - @$this->connection = new \mysqli( - $this->config['host'], - $this->config['username'], - $this->config['password'], - $this->config['database'], - $this->config['port'] - ); - - if ($this->connection->connect_error) - throw new \InvalidArgumentException("Could not connect to MySQL database. ". - $this->connection->connect_error, $this->connection->connect_errno); + try { + $this->connection = self::prepareConnection($config); + } catch (Exception $e) { + // throw with message + throw new InvalidArgumentException("Could not connect to MySQL database. ". + $e->getMessage(), $e->getCode()); + } + $this->database = Arr::get($config, 'database', config('database.connections.mysql.database')); $this->connection->query("SET names 'utf8'"); } - public function table($table_name, $no_prefix = false) + /** + * Try to connect to the database with given config. + * + * @param array $config + * @return \mysqli + * + * @throws InvalidArgumentException + */ + public static function prepareConnection($config = null) { - if ($this->connection->real_escape_string($table_name) == $table_name) { - $this->table_name = $no_prefix ? "{$this->config['database']}.$table_name" : config('database.connections.mysql.prefix').$table_name; + $config = $config ?: config('database.connections.mysql'); + + // use error control operator to hide warnings + @$conn = new \mysqli( + $config['host'], + $config['username'], + $config['password'], + $config['database'], + $config['port'] + ); + + if ($conn->connect_error) { + throw new InvalidArgumentException($conn->connect_error, $conn->connect_errno); + } + + return $conn; + } + + public function table($tableName, $no_prefix = false) + { + if ($this->connection->real_escape_string($tableName) == $tableName) { + + $this->tableName = $no_prefix ? "{$this->database}.$tableName" : config('database.connections.mysql.prefix').$tableName; return $this; + } else { - throw new \InvalidArgumentException('Table name contains invalid characters', 1); + throw new InvalidArgumentException('Table name contains invalid characters', 1); } } public function query($sql) { // compile patterns - $sql = str_replace('{table}', $this->table_name, $sql); + $sql = str_replace('{table}', $this->tableName, $sql); $result = $this->connection->query($sql); + if ($this->connection->error) - throw new \Exception("Database query error: ".$this->connection->error.", Statement: ".$sql, -1); + throw new Exception("Database query error: ".$this->connection->error.", Statement: ".$sql, -1); return $result; } @@ -94,7 +123,7 @@ class Database */ public function select($key, $value, $condition = null, $table = null, $dont_fetch_array = false) { - $table = is_null($table) ? $this->table_name : $table; + $table = $table ?: $this->tableName; if (isset($condition['where'])) { $sql = "SELECT * FROM $table".$this->where($condition); @@ -114,7 +143,7 @@ class Database { $keys = ""; $values = ""; - $table = is_null($table) ? $this->table_name : $table; + $table = $table ?: $this->tableName; foreach($data as $key => $value) { if ($value == end($data)) { @@ -135,34 +164,39 @@ class Database return ($this->getNumRows($key, $value, $table) != 0) ? true : false; } - public function hasTable($table_name) + public function hasTable($tableName) { - $sql = "SELECT table_name FROM `INFORMATION_SCHEMA`.`TABLES` WHERE (table_name = '$table_name') AND TABLE_SCHEMA='".$this->config['database']."'"; + $sql = "SELECT table_name FROM `INFORMATION_SCHEMA`.`TABLES` WHERE (table_name = '$tableName') AND TABLE_SCHEMA='{$this->database}'"; + return ($this->query($sql)->num_rows != 0) ? true : false; } public function update($key, $value, $condition = null, $table = null) { - $table = is_null($table) ? $this->table_name : $table; + $table = $table ?: $this->tableName; + return $this->query("UPDATE $table SET `$key`='$value'".$this->where($condition)); } public function delete($condition = null, $table = null) { - $table = is_null($table) ? $this->table_name : $table; + $table = $table ?: $this->tableName; + return $this->query("DELETE FROM $table".$this->where($condition)); } public function getNumRows($key, $value, $table = null) { - $table = is_null($table) ? $this->table_name : $table; + $table = $table ?: $this->tableName; + $sql = "SELECT * FROM $table WHERE $key='$value'"; return $this->query($sql)->num_rows; } public function getRecordNum($table = null) { - $table = is_null($table) ? $this->table_name : $table; + $table = $table ?: $this->tableName; + $sql = "SELECT * FROM $table WHERE 1"; return $this->query($sql)->num_rows; } @@ -176,6 +210,7 @@ class Database private function where($condition) { $statement = ""; + if (isset($condition['where']) && $condition['where'] != "") { $statement .= ' WHERE '.$condition['where']; } @@ -185,6 +220,7 @@ class Database if (isset($condition['limit'])) { $statement .= ' LIMIT '.$condition['limit']; } + return $statement; } diff --git a/app/Services/Utils.php b/app/Services/Utils.php index 0a08f813..25662448 100644 --- a/app/Services/Utils.php +++ b/app/Services/Utils.php @@ -140,13 +140,4 @@ class Utils return $str; } - public static function checkTextureDirectory() - { - if (!Storage::disk('storage')->has('textures')) { - // mkdir - if (!Storage::disk('storage')->makeDirectory('textures')) - throw new PrettyPageException(trans('setup.file.permission-error'), -1); - } - } - }