Initial commit
This commit is contained in:
50
core/lib/Thelia/Install/BaseInstall.php
Normal file
50
core/lib/Thelia/Install/BaseInstall.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install;
|
||||
|
||||
use Thelia\Install\Exception\AlreadyInstallException;
|
||||
|
||||
/**
|
||||
* Class BaseInstall
|
||||
*
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
abstract class BaseInstall
|
||||
{
|
||||
/** @var bool If Installation wizard is launched by CLI */
|
||||
protected $isConsoleMode = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param bool $verifyInstall Verify if an installation already exists
|
||||
*
|
||||
* @throws Exception\AlreadyInstallException
|
||||
*/
|
||||
public function __construct($verifyInstall = true)
|
||||
{
|
||||
// Check if install wizard is launched via CLI
|
||||
if (php_sapi_name() == 'cli') {
|
||||
$this->isConsoleMode = true;
|
||||
} else {
|
||||
$this->isConsoleMode = false;
|
||||
}
|
||||
if (file_exists(THELIA_CONF_DIR . '/database.yml') && $verifyInstall) {
|
||||
throw new AlreadyInstallException("Thelia is already installed");
|
||||
}
|
||||
|
||||
$this->exec();
|
||||
}
|
||||
|
||||
abstract public function exec();
|
||||
}
|
||||
104
core/lib/Thelia/Install/CheckDatabaseConnection.php
Normal file
104
core/lib/Thelia/Install/CheckDatabaseConnection.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install;
|
||||
|
||||
use PDO;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
|
||||
/**
|
||||
* Class CheckDatabaseConnection
|
||||
*
|
||||
* Take care of integration tests (database connection)
|
||||
*
|
||||
* @package Thelia\Install
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
*/
|
||||
class CheckDatabaseConnection extends BaseInstall
|
||||
{
|
||||
protected $validationMessages = array();
|
||||
|
||||
/** @var bool If permissions are OK */
|
||||
protected $isValid = true;
|
||||
|
||||
/** @var TranslatorInterface Translator Service */
|
||||
protected $translator = null;
|
||||
|
||||
/** @var string Database host information */
|
||||
protected $host = null;
|
||||
|
||||
/** @var string Database user information */
|
||||
protected $user = null;
|
||||
|
||||
/** @var string Database password information */
|
||||
protected $password = null;
|
||||
|
||||
/** @var int Database port information */
|
||||
protected $port = null;
|
||||
|
||||
/**
|
||||
* @var \PDO instance
|
||||
*/
|
||||
protected $connection = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $host Database host information
|
||||
* @param string $user Database user information
|
||||
* @param string $password Database password information
|
||||
* @param int $port Database port information
|
||||
* @param bool $verifyInstall If verify install
|
||||
* @param Translator $translator Translator Service
|
||||
* necessary for install wizard
|
||||
*/
|
||||
public function __construct($host, $user, $password, $port, $verifyInstall = true, Translator $translator = null)
|
||||
{
|
||||
$this->host = $host;
|
||||
$this->user = $user;
|
||||
$this->password = $password;
|
||||
$this->port = $port;
|
||||
|
||||
parent::__construct($verifyInstall);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform database connection check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
$dsn = "mysql:host=%s;port=%s";
|
||||
|
||||
try {
|
||||
$this->connection = new \PDO(
|
||||
sprintf($dsn, $this->host, $this->port),
|
||||
$this->user,
|
||||
$this->password
|
||||
);
|
||||
} catch (\PDOException $e) {
|
||||
$this->validationMessages = 'Wrong connection information';
|
||||
|
||||
$this->isValid = false;
|
||||
}
|
||||
|
||||
return $this->isValid;
|
||||
}
|
||||
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
}
|
||||
395
core/lib/Thelia/Install/CheckPermission.php
Normal file
395
core/lib/Thelia/Install/CheckPermission.php
Normal file
@@ -0,0 +1,395 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install;
|
||||
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
|
||||
/**
|
||||
* Class CheckPermission
|
||||
*
|
||||
* Take care of integration tests (files permissions)
|
||||
*
|
||||
* @package Thelia\Install
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
*/
|
||||
class CheckPermission extends BaseInstall
|
||||
{
|
||||
const DIR_CONF = 'local/config';
|
||||
const DIR_LOG = 'log';
|
||||
const DIR_CACHE = 'cache';
|
||||
const DIR_WEB = 'web';
|
||||
const DIR_SESSION = 'local/session';
|
||||
const DIR_MEDIA = 'local/media';
|
||||
|
||||
/** @var array Directory needed to be writable */
|
||||
protected $directoriesToBeWritable = array(
|
||||
self::DIR_CONF,
|
||||
self::DIR_LOG,
|
||||
self::DIR_CACHE,
|
||||
self::DIR_WEB,
|
||||
self::DIR_SESSION,
|
||||
self::DIR_MEDIA
|
||||
);
|
||||
|
||||
/** @var array Minimum server configuration necessary */
|
||||
protected $minServerConfigurationNecessary = array(
|
||||
'memory_limit' => 134217728,
|
||||
'post_max_size' => 20971520,
|
||||
'upload_max_filesize' => 2097152
|
||||
);
|
||||
|
||||
protected $phpExpectedVerions = array(
|
||||
'min' => '5.5',
|
||||
'max' => '7.4'
|
||||
);
|
||||
|
||||
protected $extensions = array(
|
||||
'curl',
|
||||
'fileinfo',
|
||||
'gd',
|
||||
'intl',
|
||||
'openssl',
|
||||
'pdo_mysql',
|
||||
'dom',
|
||||
'zip'
|
||||
);
|
||||
|
||||
protected $validationMessages = array();
|
||||
|
||||
/** @var bool If permissions are OK */
|
||||
protected $isValid = true;
|
||||
|
||||
/** @var TranslatorInterface Translator Service */
|
||||
protected $translator = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param bool $verifyInstall If verify install
|
||||
* @param Translator $translator Translator Service
|
||||
* necessary for install wizard
|
||||
*/
|
||||
public function __construct($verifyInstall = true, Translator $translator = null)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
|
||||
$this->validationMessages['php_version'] = array(
|
||||
'text' => $this->getI18nPhpVersionText(phpversion(), true),
|
||||
'hint' => $this->getI18nPhpVersionHint(),
|
||||
'status' => true
|
||||
);
|
||||
|
||||
foreach ($this->directoriesToBeWritable as $directory) {
|
||||
$this->validationMessages[$directory] = array(
|
||||
'text' => '',
|
||||
'hint' => '',
|
||||
'status' => true
|
||||
);
|
||||
}
|
||||
foreach ($this->minServerConfigurationNecessary as $key => $value) {
|
||||
$this->validationMessages[$key] = array(
|
||||
'text' => '',
|
||||
'hint' => $this->getI18nConfigHint(),
|
||||
'status' => true
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
$this->validationMessages[$extension] = array(
|
||||
'text' => '',
|
||||
'hint' => $this->getI18nExtensionHint(),
|
||||
'status' => true,
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct($verifyInstall);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform file permission check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
if (version_compare(phpversion(), $this->phpExpectedVerions['min'], '<') || version_compare(phpversion(), $this->phpExpectedVerions['max'], '>=')) {
|
||||
$this->isValid = false;
|
||||
$this->validationMessages['php_version']['text'] = $this->getI18nPhpVersionText(phpversion(), false);
|
||||
$this->validationMessages['php_version']['status'] = false;
|
||||
$this->validationMessages['php_version']['hint'] = $this->getI18nPhpVersionHint();
|
||||
}
|
||||
|
||||
foreach ($this->directoriesToBeWritable as $directory) {
|
||||
$fullDirectory = THELIA_ROOT . $directory;
|
||||
$this->validationMessages[$directory]['text'] = $this->getI18nDirectoryText($fullDirectory, true);
|
||||
if (is_writable($fullDirectory) === false) {
|
||||
if (!$this->makeDirectoryWritable($fullDirectory)) {
|
||||
$this->isValid = false;
|
||||
$this->validationMessages[$directory]['status'] = false;
|
||||
$this->validationMessages[$directory]['text'] = $this->getI18nDirectoryText($fullDirectory, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->minServerConfigurationNecessary as $key => $value) {
|
||||
$this->validationMessages[$key]['text'] = $this->getI18nConfigText($key, $this->formatBytes($value), ini_get($key), true);
|
||||
if (!$this->verifyServerMemoryValues($key, $value)) {
|
||||
$this->isValid = false;
|
||||
$this->validationMessages[$key]['status'] = false;
|
||||
$this->validationMessages[$key]['text'] = $this->getI18nConfigText($key, $this->formatBytes($value), ini_get($key), false);
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
$this->validationMessages[$extension]['text'] = $this->getI18nExtensionText($extension, true);
|
||||
if (false === extension_loaded($extension)) {
|
||||
$this->isValid = false;
|
||||
$this->validationMessages[$extension]['status'] = false;
|
||||
$this->validationMessages[$extension]['text'] = $this->getI18nExtensionText($extension, false);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validation messages
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getValidationMessages()
|
||||
{
|
||||
return $this->validationMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a directory writable (recursively)
|
||||
*
|
||||
* @param string $directory path to directory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function makeDirectoryWritable($directory)
|
||||
{
|
||||
return (is_writable(THELIA_ROOT . $directory) === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Translated text about the directory state
|
||||
*
|
||||
* @param string $directory Directory being checked
|
||||
* @param bool $isValid If directory permission is valid
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getI18nDirectoryText($directory, $isValid)
|
||||
{
|
||||
if ($this->translator !== null) {
|
||||
if ($isValid) {
|
||||
$sentence = 'The directory %directory% is writable';
|
||||
} else {
|
||||
$sentence = 'The directory %directory% is not writable';
|
||||
}
|
||||
|
||||
$translatedText = $this->translator->trans(
|
||||
$sentence,
|
||||
array(
|
||||
'%directory%' => $directory
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$translatedText = sprintf('The directory %s should be writable', $directory);
|
||||
}
|
||||
|
||||
return $translatedText;
|
||||
}
|
||||
|
||||
protected function getI18nExtensionText($extension, $isValid)
|
||||
{
|
||||
if ($isValid) {
|
||||
$sentence = '%extension% php extension is loaded.';
|
||||
} else {
|
||||
$sentence = '%extension% php extension is not loaded.';
|
||||
}
|
||||
|
||||
return $this->translator->trans($sentence, array(
|
||||
'%extension%' => $extension
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Translated text about the directory state
|
||||
* Not usable with CLI
|
||||
*
|
||||
* @param string $key .ini file key
|
||||
* @param string $expectedValue Expected server value
|
||||
* @param string $currentValue Actual server value
|
||||
* @param bool $isValid If server configuration is valid
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getI18nConfigText($key, $expectedValue, $currentValue, $isValid)
|
||||
{
|
||||
if ($isValid) {
|
||||
$sentence = 'The PHP "%key%" configuration value (currently %currentValue%) is correct (%expectedValue% required).';
|
||||
} else {
|
||||
$sentence = 'The PHP "%key%" configuration value (currently %currentValue%) is below minimal requirements to run Thelia2 (%expectedValue% required).';
|
||||
}
|
||||
|
||||
$translatedText = $this->translator->trans(
|
||||
$sentence,
|
||||
array(
|
||||
'%key%' => $key,
|
||||
'%expectedValue%' => $expectedValue,
|
||||
'%currentValue%' => $currentValue,
|
||||
),
|
||||
'install-wizard'
|
||||
);
|
||||
|
||||
return $translatedText;
|
||||
}
|
||||
|
||||
protected function getI18nExtensionHint()
|
||||
{
|
||||
return $this->translator->trans('This PHP extension should be installed and loaded.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Translated hint about the config requirement issue
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getI18nConfigHint()
|
||||
{
|
||||
$sentence = 'Change this value in the php.ini configuration file.';
|
||||
$translatedText = $this->translator->trans(
|
||||
$sentence
|
||||
);
|
||||
|
||||
return $translatedText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Translated hint about the PHP version requirement issue
|
||||
*
|
||||
* @param string $expectedValue
|
||||
* @param string $currentValue
|
||||
* @param bool $isValid
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getI18nPhpVersionText($currentValue, $isValid)
|
||||
{
|
||||
if ($this->translator !== null) {
|
||||
if ($isValid) {
|
||||
$sentence = 'PHP version %currentValue% matches the version required (> %minExpectedValue% < %maxExpectedValue%).';
|
||||
} else {
|
||||
$sentence = 'The installer detected PHP version %currentValue%, but Thelia 2 requires PHP between %minExpectedValue% and %maxExpectedValue%.';
|
||||
}
|
||||
|
||||
$translatedText = $this->translator->trans(
|
||||
$sentence,
|
||||
array(
|
||||
'%minExpectedValue%' => $this->phpExpectedVerions['min'],
|
||||
'%maxExpectedValue%' => $this->phpExpectedVerions['max'],
|
||||
'%currentValue%' => $currentValue,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$translatedText = sprintf('Thelia requires PHP between %s and %s (%s currently).', $this->phpExpectedVerions['min'], $this->phpExpectedVerions['max'], $currentValue);
|
||||
}
|
||||
|
||||
return $translatedText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Translated hint about the config requirement issue
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getI18nPhpVersionHint()
|
||||
{
|
||||
$sentence = 'You should change the installed PHP version to continue Thelia 2 installation.';
|
||||
$translatedText = $this->translator->trans(
|
||||
$sentence,
|
||||
array()
|
||||
);
|
||||
|
||||
return $translatedText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a server memory value is met or not
|
||||
*
|
||||
* @param string $key .ini file key
|
||||
* @param int $necessaryValueInBytes Expected value in bytes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function verifyServerMemoryValues($key, $necessaryValueInBytes)
|
||||
{
|
||||
$serverValueInBytes = $this->returnBytes(ini_get($key));
|
||||
|
||||
if ($serverValueInBytes == -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ($serverValueInBytes >= $necessaryValueInBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bytes from memory .ini value
|
||||
*
|
||||
* @param string $val .ini value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function returnBytes($val)
|
||||
{
|
||||
$val = trim($val);
|
||||
$last = strtolower($val[strlen($val)-1]);
|
||||
// Do not add breaks in the switch below
|
||||
switch ($last) {
|
||||
// The 'G' modifier is available since PHP 5.1.0
|
||||
case 'g':
|
||||
$val = (int)$val*1024;
|
||||
// no break
|
||||
case 'm':
|
||||
$val = (int)$val*1024;
|
||||
// no break
|
||||
case 'k':
|
||||
$val = (int)$val*1024;
|
||||
}
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert bytes to readable string
|
||||
*
|
||||
* @param int $bytes bytes
|
||||
* @param int $precision conversion precision
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatBytes($bytes, $precision = 2)
|
||||
{
|
||||
$base = log($bytes) / log(1024);
|
||||
$suffixes = array('', 'k', 'M', 'G', 'T');
|
||||
|
||||
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
||||
}
|
||||
}
|
||||
280
core/lib/Thelia/Install/Database.php
Normal file
280
core/lib/Thelia/Install/Database.php
Normal file
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install;
|
||||
|
||||
use PDO;
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Propel\Runtime\Connection\ConnectionWrapper;
|
||||
use Propel\Runtime\Propel;
|
||||
use Propel\Runtime\ServiceContainer\ServiceContainerInterface;
|
||||
use Thelia\Log\Tlog;
|
||||
|
||||
/**
|
||||
* Class Database
|
||||
* @package Thelia\Install
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Database
|
||||
{
|
||||
/**
|
||||
* @var \PDO
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Create a new instance, using the provided connection information, either none for
|
||||
* automatically a connection, a ConnectionWrapper instance (through ConnectionInterface) or a PDO connection.
|
||||
*
|
||||
* @param ConnectionInterface|\PDO|null $connection the connection object
|
||||
* @throws \InvalidArgumentException if $connection is not of the suitable type.
|
||||
*/
|
||||
public function __construct($connection = null)
|
||||
{
|
||||
// Get a connection from Propel if we don't have one
|
||||
if (null == $connection) {
|
||||
$connection = Propel::getConnection(ServiceContainerInterface::CONNECTION_WRITE);
|
||||
}
|
||||
|
||||
// Get the PDO connection from an
|
||||
if ($connection instanceof ConnectionWrapper) {
|
||||
$connection = $connection->getWrappedConnection();
|
||||
}
|
||||
|
||||
if (!$connection instanceof \PDO) {
|
||||
throw new \InvalidArgumentException("A PDO connection should be provided");
|
||||
}
|
||||
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert all sql needed in database
|
||||
* Default insert /install/thelia.sql and /install/insert.sql
|
||||
*
|
||||
* @param string $dbName Database name
|
||||
* @param array $extraSqlFiles SQL Files uri to insert
|
||||
*/
|
||||
public function insertSql($dbName = null, array $extraSqlFiles = null)
|
||||
{
|
||||
if ($dbName) {
|
||||
$this->connection->query(sprintf("use `%s`", $dbName));
|
||||
}
|
||||
|
||||
$sql = array();
|
||||
|
||||
if (null === $extraSqlFiles) {
|
||||
$sql = array_merge(
|
||||
$sql,
|
||||
$this->prepareSql(file_get_contents(THELIA_SETUP_DIRECTORY . 'thelia.sql')),
|
||||
$this->prepareSql(file_get_contents(THELIA_SETUP_DIRECTORY . 'insert.sql'))
|
||||
);
|
||||
} else {
|
||||
foreach ($extraSqlFiles as $fileToInsert) {
|
||||
$sql = array_merge(
|
||||
$sql,
|
||||
$this->prepareSql(file_get_contents($fileToInsert))
|
||||
);
|
||||
}
|
||||
}
|
||||
$size = \count($sql);
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
if (!empty($sql[$i])) {
|
||||
$this->execute($sql[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wrapper around PDO::exec
|
||||
*
|
||||
* @param string $sql SQL query
|
||||
* @param array $args SQL request parameters (PDO style)
|
||||
* @throws \RuntimeException|\PDOException if something goes wrong.
|
||||
* @return \PDOStatement
|
||||
*/
|
||||
public function execute($sql, $args = array())
|
||||
{
|
||||
$stmt = $this->connection->prepare($sql);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new \RuntimeException("Failed to prepare statement for $sql: " . print_r($this->connection->errorInfo(), 1));
|
||||
}
|
||||
|
||||
$success = $stmt->execute($args);
|
||||
|
||||
if ($success === false || $stmt->errorCode() != 0) {
|
||||
throw new \RuntimeException("Failed to execute SQL '$sql', arguments:" . print_r($args, 1).", error:".print_r($stmt->errorInfo(), 1));
|
||||
}
|
||||
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Separate each sql instruction in an array
|
||||
*
|
||||
* @param $sql
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareSql($sql)
|
||||
{
|
||||
$sql = str_replace(";',", "-CODE-", $sql);
|
||||
$sql = trim($sql);
|
||||
preg_match_all('#DELIMITER (.+?)\n(.+?)DELIMITER ;#s', $sql, $m);
|
||||
foreach ($m[0] as $k => $v) {
|
||||
if ($m[1][$k] == '|') {
|
||||
throw new \RuntimeException('You can not use "|" as delimiter: '.$v);
|
||||
}
|
||||
$stored = str_replace(';', '|', $m[2][$k]);
|
||||
$stored = str_replace($m[1][$k], ";\n", $stored);
|
||||
$sql = str_replace($v, $stored, $sql);
|
||||
}
|
||||
$query = array();
|
||||
|
||||
$tab = explode(";\n", $sql);
|
||||
$size = \count($tab);
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
$queryTemp = str_replace("-CODE-", ";',", $tab[$i]);
|
||||
$queryTemp = str_replace("|", ";", $queryTemp);
|
||||
$query[] = $queryTemp;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backup the db OR just a table
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $tables
|
||||
*/
|
||||
public function backupDb($filename, $tables = '*')
|
||||
{
|
||||
$data = [];
|
||||
|
||||
// get all of the tables
|
||||
if ($tables == '*') {
|
||||
$tables = array();
|
||||
$result = $this->connection->prepare('SHOW TABLES');
|
||||
$result->execute();
|
||||
while ($row = $result->fetch(PDO::FETCH_NUM)) {
|
||||
$tables[] = $row[0];
|
||||
}
|
||||
} else {
|
||||
$tables = \is_array($tables) ? $tables : explode(',', $tables);
|
||||
}
|
||||
|
||||
$data[] = "\n";
|
||||
$data[] = 'SET foreign_key_checks=0;';
|
||||
$data[] = "\n\n";
|
||||
|
||||
foreach ($tables as $table) {
|
||||
if (!preg_match("/^[\w_\-]+$/", $table)) {
|
||||
Tlog::getInstance()->alert(
|
||||
sprintf(
|
||||
"Attempt to backup the db with this invalid table name: '%s'",
|
||||
$table
|
||||
)
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->execute('SELECT * FROM `' . $table . '`');
|
||||
|
||||
$fieldCount = $result->columnCount();
|
||||
|
||||
$data[] = 'DROP TABLE `' . $table . '`;';
|
||||
|
||||
$resultStruct = $this->execute('SHOW CREATE TABLE `' . $table . '`');
|
||||
|
||||
$rowStruct = $resultStruct->fetch(PDO::FETCH_NUM);
|
||||
|
||||
$data[] = "\n\n";
|
||||
$data[] = $rowStruct[1];
|
||||
$data[] = ";\n\n";
|
||||
|
||||
for ($i = 0; $i < $fieldCount; $i++) {
|
||||
while ($row = $result->fetch(PDO::FETCH_NUM)) {
|
||||
$data[] = 'INSERT INTO `' . $table . '` VALUES(';
|
||||
for ($j = 0; $j < $fieldCount; $j++) {
|
||||
$row[$j] = addslashes($row[$j]);
|
||||
$row[$j] = str_replace("\n", "\\n", $row[$j]);
|
||||
if (isset($row[$j])) {
|
||||
$data[] = '"' . $row[$j] . '"';
|
||||
} else {
|
||||
$data[] = '""';
|
||||
}
|
||||
if ($j < ($fieldCount - 1)) {
|
||||
$data[] = ',';
|
||||
}
|
||||
}
|
||||
$data[] = ");\n";
|
||||
}
|
||||
}
|
||||
$data[] = "\n\n\n";
|
||||
}
|
||||
|
||||
$data[] = 'SET foreign_key_checks=1;';
|
||||
|
||||
//save filename
|
||||
$this->writeFilename($filename, $data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restore a file in the current db
|
||||
*
|
||||
* @param string $filename the file containing sql queries
|
||||
*/
|
||||
public function restoreDb($filename)
|
||||
{
|
||||
$this->insertSql(null, [$filename]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an array of data to a filename
|
||||
*
|
||||
* @param string $filename
|
||||
* @param array $data
|
||||
*/
|
||||
private function writeFilename($filename, $data)
|
||||
{
|
||||
$f = fopen($filename, "w+");
|
||||
|
||||
fwrite($f, implode('', $data));
|
||||
fclose($f);
|
||||
}
|
||||
|
||||
/**
|
||||
* create database if not exists
|
||||
*
|
||||
* @param $dbName
|
||||
*/
|
||||
public function createDatabase($dbName)
|
||||
{
|
||||
$this->execute(
|
||||
sprintf(
|
||||
"CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET utf8",
|
||||
$dbName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PDO
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install\Exception;
|
||||
|
||||
/**
|
||||
* Class AlreadyInstallException
|
||||
* @package Thelia\Install\Exception
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class AlreadyInstallException extends InstallException
|
||||
{
|
||||
}
|
||||
21
core/lib/Thelia/Install/Exception/InstallException.php
Normal file
21
core/lib/Thelia/Install/Exception/InstallException.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install\Exception;
|
||||
|
||||
/**
|
||||
* Class InstallException
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class InstallException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
22
core/lib/Thelia/Install/Exception/UpToDateException.php
Normal file
22
core/lib/Thelia/Install/Exception/UpToDateException.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install\Exception;
|
||||
|
||||
/**
|
||||
* Class UpToDateException
|
||||
* @package Thelia\Install\Exception
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class UpToDateException extends InstallException
|
||||
{
|
||||
}
|
||||
41
core/lib/Thelia/Install/Exception/UpdateException.php
Normal file
41
core/lib/Thelia/Install/Exception/UpdateException.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace Thelia\Install\Exception;
|
||||
|
||||
/**
|
||||
* Class UpdateException
|
||||
* @package Thelia\Install\Exception
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
class UpdateException extends \RuntimeException
|
||||
{
|
||||
/** @var string the version that has failed */
|
||||
protected $version = null;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $version
|
||||
*/
|
||||
public function setVersion($version)
|
||||
{
|
||||
$this->version = $version;
|
||||
}
|
||||
}
|
||||
600
core/lib/Thelia/Install/Update.php
Normal file
600
core/lib/Thelia/Install/Update.php
Normal file
@@ -0,0 +1,600 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Install;
|
||||
|
||||
use Michelf\Markdown;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Thelia\Config\DatabaseConfigurationSource;
|
||||
use Thelia\Install\Exception\UpdateException;
|
||||
use Thelia\Install\Exception\UpToDateException;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Tools\Version\Version;
|
||||
|
||||
/**
|
||||
* Class Update
|
||||
* @package Thelia\Install
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Update
|
||||
{
|
||||
const SQL_DIR = 'update/sql/';
|
||||
|
||||
const PHP_DIR = 'update/php/';
|
||||
|
||||
const INSTRUCTION_DIR = 'update/instruction/';
|
||||
|
||||
protected $version = null;
|
||||
|
||||
/** @var bool */
|
||||
protected $usePropel = null;
|
||||
|
||||
/** @var null|Tlog */
|
||||
protected $logger = null;
|
||||
|
||||
/** @var array log messages */
|
||||
protected $logs = [];
|
||||
|
||||
/** @var array post instructions */
|
||||
protected $postInstructions = [];
|
||||
|
||||
/** @var array */
|
||||
protected $updatedVersions = [];
|
||||
|
||||
/** @var PDO */
|
||||
protected $connection = null;
|
||||
|
||||
/** @var string|null */
|
||||
protected $backupFile = null;
|
||||
|
||||
/** @var string */
|
||||
protected $backupDir = 'local/backup/';
|
||||
|
||||
/** @var array */
|
||||
protected $messages = [];
|
||||
|
||||
/** @var Translator */
|
||||
protected $translator;
|
||||
|
||||
public function __construct($usePropel = true)
|
||||
{
|
||||
$this->usePropel = $usePropel;
|
||||
|
||||
if ($this->usePropel) {
|
||||
$this->logger = Tlog::getInstance();
|
||||
$this->logger->setLevel(Tlog::DEBUG);
|
||||
} else {
|
||||
$this->logs = [];
|
||||
}
|
||||
|
||||
$dbConfig = null;
|
||||
|
||||
try {
|
||||
$this->connection = $this->getDatabasePDO();
|
||||
} catch (ParseException $ex) {
|
||||
throw new UpdateException("database.yml is not a valid file : " . $ex->getMessage());
|
||||
} catch (\PDOException $ex) {
|
||||
throw new UpdateException('Wrong connection information' . $ex->getMessage());
|
||||
}
|
||||
|
||||
$this->version = $this->getVersionList();
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve the database connection
|
||||
*
|
||||
* @return \PDO
|
||||
* @throws ParseException
|
||||
* @throws \PDOException
|
||||
*/
|
||||
protected function getDatabasePDO()
|
||||
{
|
||||
$configPath = THELIA_CONF_DIR . "database.yml";
|
||||
|
||||
if (!file_exists($configPath)) {
|
||||
throw new UpdateException("Thelia is not installed yet");
|
||||
}
|
||||
|
||||
$definePropel = new DatabaseConfigurationSource(
|
||||
Yaml::parse(file_get_contents($configPath)),
|
||||
$this->getEnvParameters()
|
||||
);
|
||||
|
||||
return $definePropel->getTheliaConnectionPDO();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the environment parameters.
|
||||
*
|
||||
* Only the parameters starting with "SYMFONY__" are considered.
|
||||
*
|
||||
* @return array An array of parameters
|
||||
*/
|
||||
protected function getEnvParameters()
|
||||
{
|
||||
$parameters = array();
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
if (0 === strpos($key, 'SYMFONY__')) {
|
||||
$parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
public function isLatestVersion($version = null)
|
||||
{
|
||||
if (null === $version) {
|
||||
$version = $this->getCurrentVersion();
|
||||
}
|
||||
$lastEntry = end($this->version);
|
||||
|
||||
return $lastEntry == $version;
|
||||
}
|
||||
|
||||
public function process()
|
||||
{
|
||||
$this->updatedVersions = array();
|
||||
|
||||
$currentVersion = $this->getCurrentVersion();
|
||||
$this->log('debug', "start update process");
|
||||
|
||||
if (true === $this->isLatestVersion($currentVersion)) {
|
||||
$this->log('debug', "You already have the latest version. No update available");
|
||||
throw new UpToDateException('You already have the latest version. No update available');
|
||||
}
|
||||
|
||||
$index = array_search($currentVersion, $this->version);
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
$database = new Database($this->connection);
|
||||
$version = null;
|
||||
|
||||
try {
|
||||
$size = \count($this->version);
|
||||
|
||||
for ($i = ++$index; $i < $size; $i++) {
|
||||
$version = $this->version[$i];
|
||||
$this->updateToVersion($version, $database);
|
||||
$this->updatedVersions[] = $version;
|
||||
}
|
||||
|
||||
$currentVersion = Version::parse();
|
||||
$this->log('debug', sprintf('setting database configuration to %s', $currentVersion['version']));
|
||||
$updateConfigVersion = [
|
||||
'thelia_version' => $currentVersion['version'],
|
||||
'thelia_major_version' => $currentVersion['major'],
|
||||
'thelia_minus_version' => $currentVersion['minus'],
|
||||
'thelia_release_version' => $currentVersion['release'],
|
||||
'thelia_extra_version' => $currentVersion['extra'],
|
||||
];
|
||||
|
||||
foreach ($updateConfigVersion as $name => $value) {
|
||||
$stmt = $this->connection->prepare('SELECT * FROM `config` WHERE `name` = ?');
|
||||
$stmt->execute([$name]);
|
||||
|
||||
if ($stmt->rowCount()) {
|
||||
$stmt = $this->connection->prepare('UPDATE `config` SET `value` = ? WHERE `name` = ?');
|
||||
$stmt->execute([$version, $value]);
|
||||
} else {
|
||||
$stmt = $this->connection->prepare('INSERT INTO `config` (?) VALUES (?)');
|
||||
$stmt->execute([$version, $value]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->connection->commit();
|
||||
$this->log('debug', 'update successfully');
|
||||
} catch (\Exception $e) {
|
||||
$this->connection->rollBack();
|
||||
|
||||
$this->log('error', sprintf('error during update process with message : %s', $e->getMessage()));
|
||||
|
||||
$ex = new UpdateException($e->getMessage(), $e->getCode(), $e->getPrevious());
|
||||
$ex->setVersion($version);
|
||||
throw $ex;
|
||||
}
|
||||
$this->log('debug', 'end of update processing');
|
||||
|
||||
return $this->updatedVersions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backup current DB to file local/backup/update.sql
|
||||
* @return bool if it succeeds, false otherwise
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function backupDb()
|
||||
{
|
||||
$database = new Database($this->connection);
|
||||
|
||||
if (! $this->checkBackupIsPossible()) {
|
||||
$message = 'Your database is too big for an automatic backup';
|
||||
|
||||
$this->log('error', $message);
|
||||
|
||||
throw new UpdateException($message);
|
||||
}
|
||||
|
||||
$this->backupFile = THELIA_ROOT . $this->backupDir . 'update.sql';
|
||||
$backupDir = THELIA_ROOT . $this->backupDir;
|
||||
|
||||
$fs = new Filesystem();
|
||||
|
||||
try {
|
||||
$this->log('debug', sprintf('Backup database to file : %s', $this->backupFile));
|
||||
|
||||
// test if backup dir exists
|
||||
if (!$fs->exists($backupDir)) {
|
||||
$fs->mkdir($backupDir);
|
||||
}
|
||||
|
||||
if (!is_writable($backupDir)) {
|
||||
throw new \RuntimeException(sprintf('impossible to write in directory : %s', $backupDir));
|
||||
}
|
||||
|
||||
// test if backup file already exists
|
||||
if ($fs->exists($this->backupFile)) {
|
||||
// remove file
|
||||
$fs->remove($this->backupFile);
|
||||
}
|
||||
|
||||
$database->backupDb($this->backupFile);
|
||||
} catch (\Exception $ex) {
|
||||
$this->log('error', sprintf('error during backup process with message : %s', $ex->getMessage()));
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores file local/backup/update.sql to current DB
|
||||
*
|
||||
* @return bool if it succeeds, false otherwise
|
||||
*/
|
||||
public function restoreDb()
|
||||
{
|
||||
$database = new Database($this->connection);
|
||||
|
||||
try {
|
||||
$this->log('debug', sprintf('Restore database with file : %s', $this->backupFile));
|
||||
|
||||
if (!file_exists($this->backupFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$database->restoreDb($this->backupFile);
|
||||
} catch (\Exception $ex) {
|
||||
$this->log('error', sprintf('error during restore process with message : %s', $ex->getMessage()));
|
||||
print $ex->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getBackupFile()
|
||||
{
|
||||
return $this->backupFile;
|
||||
}
|
||||
|
||||
public function getLogs()
|
||||
{
|
||||
return $this->logs;
|
||||
}
|
||||
|
||||
protected function log($level, $message)
|
||||
{
|
||||
if ($this->usePropel) {
|
||||
switch ($level) {
|
||||
case 'debug':
|
||||
$this->logger->debug($message);
|
||||
break;
|
||||
case 'info':
|
||||
$this->logger->info($message);
|
||||
break;
|
||||
case 'notice':
|
||||
$this->logger->notice($message);
|
||||
break;
|
||||
case 'warning':
|
||||
$this->logger->warning($message);
|
||||
break;
|
||||
case 'error':
|
||||
$this->logger->error($message);
|
||||
break;
|
||||
case 'critical':
|
||||
$this->logger->critical($message);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$this->logs[] = [$level, $message];
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateToVersion($version, Database $database)
|
||||
{
|
||||
// sql update
|
||||
$filename = sprintf(
|
||||
"%s%s%s",
|
||||
THELIA_SETUP_DIRECTORY,
|
||||
str_replace('/', DS, self::SQL_DIR),
|
||||
$version . '.sql'
|
||||
);
|
||||
|
||||
if (file_exists($filename)) {
|
||||
$this->log('debug', sprintf('inserting file %s', $version . '.sql'));
|
||||
$database->insertSql(null, [$filename]);
|
||||
$this->log('debug', sprintf('end inserting file %s', $version . '.sql'));
|
||||
}
|
||||
|
||||
// php update
|
||||
$filename = sprintf(
|
||||
"%s%s%s",
|
||||
THELIA_SETUP_DIRECTORY,
|
||||
str_replace('/', DS, self::PHP_DIR),
|
||||
$version . '.php'
|
||||
);
|
||||
|
||||
if (file_exists($filename)) {
|
||||
$this->log('debug', sprintf('executing file %s', $version . '.php'));
|
||||
include_once($filename);
|
||||
$this->log('debug', sprintf('end executing file %s', $version . '.php'));
|
||||
}
|
||||
|
||||
// instructions
|
||||
$filename = sprintf(
|
||||
"%s%s%s",
|
||||
THELIA_SETUP_DIRECTORY,
|
||||
str_replace('/', DS, self::INSTRUCTION_DIR),
|
||||
$version . '.md'
|
||||
);
|
||||
|
||||
if (file_exists($filename)) {
|
||||
$this->addPostInstructions($version, file_get_contents($filename));
|
||||
}
|
||||
|
||||
$this->setCurrentVersion($version);
|
||||
}
|
||||
|
||||
public function getCurrentVersion()
|
||||
{
|
||||
$stmt = $this->connection->query("SELECT `value` FROM `config` WHERE name='thelia_version'");
|
||||
|
||||
return $stmt->fetchColumn();
|
||||
}
|
||||
|
||||
public function setCurrentVersion($version)
|
||||
{
|
||||
$currentVersion = null;
|
||||
|
||||
if (null !== $this->connection) {
|
||||
try {
|
||||
$stmt = $this->connection->prepare('UPDATE config set value = ? where name = ?');
|
||||
$stmt->execute([$version, 'thelia_version']);
|
||||
} catch (PDOException $e) {
|
||||
$this->log('error', sprintf('Error setting current version : %s', $e->getMessage()));
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database size in Mo
|
||||
* @return float
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getDataBaseSize()
|
||||
{
|
||||
$stmt = $this->connection->query(
|
||||
"SELECT sum(data_length) / 1024 / 1024 'size' FROM information_schema.TABLES WHERE table_schema = DATABASE() GROUP BY table_schema"
|
||||
);
|
||||
|
||||
if ($stmt->rowCount()) {
|
||||
return \floatval($stmt->fetch(PDO::FETCH_OBJ)->size);
|
||||
}
|
||||
|
||||
throw new \Exception('Impossible to calculate the database size');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether it is possible to make a data base backup
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkBackupIsPossible()
|
||||
{
|
||||
$size = 0;
|
||||
if (preg_match('/^(\d+)(.)$/', ini_get('memory_limit'), $matches)) {
|
||||
switch (strtolower($matches[2])) {
|
||||
case 'k':
|
||||
$size = $matches[1] / 1024;
|
||||
break;
|
||||
case 'm':
|
||||
$size = $matches[1];
|
||||
break;
|
||||
case 'g':
|
||||
$size = $matches[1] * 1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getDataBaseSize() > ($size - 64) / 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getLatestVersion()
|
||||
{
|
||||
return end($this->version);
|
||||
}
|
||||
|
||||
public function getVersions()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getUpdatedVersions()
|
||||
{
|
||||
return $this->updatedVersions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $updatedVersions
|
||||
*/
|
||||
public function setUpdatedVersions($updatedVersions)
|
||||
{
|
||||
$this->updatedVersions = $updatedVersions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new post update instruction
|
||||
*
|
||||
* @param string $instructions content of the instruction un markdown format
|
||||
*/
|
||||
protected function addPostInstructions($version, $instructions)
|
||||
{
|
||||
if (!isset($this->postInstructions[$version])) {
|
||||
$this->postInstructions[$version] = [];
|
||||
}
|
||||
|
||||
$this->postInstructions[$version][] = $instructions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content of all instructions
|
||||
*
|
||||
* @param string $format the format of the export : plain (default) or html
|
||||
* @return string the instructions in plain text or html
|
||||
*/
|
||||
public function getPostInstructions($format = 'plain')
|
||||
{
|
||||
$content = [];
|
||||
|
||||
if (\count($this->postInstructions) == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ksort($this->postInstructions);
|
||||
|
||||
foreach ($this->postInstructions as $version => $instructions) {
|
||||
$content[] = sprintf("## %s", $version);
|
||||
foreach ($instructions as $instruction) {
|
||||
$content[] = sprintf("%s", $instruction);
|
||||
}
|
||||
}
|
||||
|
||||
$content = implode("\n\n", $content);
|
||||
|
||||
if ($format === 'html') {
|
||||
$content = Markdown::defaultTransform($content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function hasPostInstructions()
|
||||
{
|
||||
return (\count($this->postInstructions) !== 0);
|
||||
}
|
||||
|
||||
public function getVersionList()
|
||||
{
|
||||
$list = [];
|
||||
$finder = new Finder();
|
||||
$path = sprintf("%s%s", THELIA_SETUP_DIRECTORY, str_replace('/', DS, self::SQL_DIR));
|
||||
$sort = function (\SplFileInfo $a, \SplFileInfo $b) {
|
||||
$a = strtolower(substr($a->getRelativePathname(), 0, -4));
|
||||
$b = strtolower(substr($b->getRelativePathname(), 0, -4));
|
||||
return version_compare($a, $b);
|
||||
};
|
||||
|
||||
$files = $finder->name('*.sql')->in($path)->sort($sort);
|
||||
foreach ($files as $file) {
|
||||
$list[] = substr($file->getRelativePathname(), 0, -4);
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string $type
|
||||
* @return $this
|
||||
*/
|
||||
public function setMessage($message, $type = 'info')
|
||||
{
|
||||
$this->messages[] = [$message, $type];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMessages()
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public function trans($string)
|
||||
{
|
||||
return $this->translator ? $this->translator->trans($string) : $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Translator $translator
|
||||
* @return $this
|
||||
*/
|
||||
public function setTranslator(Translator $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getWebVersion()
|
||||
{
|
||||
$url = "http://thelia.net/version.php";
|
||||
$curl = curl_init($url);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_HEADER, false);
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 5);
|
||||
$res = curl_exec($curl);
|
||||
|
||||
try {
|
||||
if (Version::parse($res)) {
|
||||
return trim($res);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user