addChamiloRequirement(
version_compare($phpVersion, self::REQUIRED_PHP_VERSION, '>='),
sprintf(
'PHP version must be at least %s (%s installed)',
self::REQUIRED_PHP_VERSION,
$phpVersion
),
sprintf(
'You are running PHP version "%s", but Chamilo needs at least PHP "%s" to run.'.
'Before using Chamilo, upgrade your PHP installation, preferably to the latest version.',
$phpVersion,
self::REQUIRED_PHP_VERSION
),
sprintf(
'Install PHP %s or newer (installed version is %s)',
self::REQUIRED_PHP_VERSION,
$phpVersion
)
);
$this->addChamiloRequirement(
null !== $gdVersion && version_compare(
$gdVersion,
self::REQUIRED_GD_VERSION,
'>='
),
'GD extension must be at least '.self::REQUIRED_GD_VERSION,
'Install and enable the GD extension at least '.self::REQUIRED_GD_VERSION.' version'
);
$this->addChamiloRequirement(
null !== $curlVersion && version_compare(
$curlVersion['version'],
self::REQUIRED_CURL_VERSION,
'>='
),
'cURL extension must be at least '.self::REQUIRED_CURL_VERSION,
'Install and enable the cURL extension at least '.self::REQUIRED_CURL_VERSION.' version'
);
$this->addChamiloRequirement(
function_exists('mb_strlen'),
'mb_strlen() should be available',
'Install and enable the mbstring extension.'
);
$this->addChamiloRequirement(
function_exists('mcrypt_encrypt'),
'mcrypt_encrypt() should be available',
'Install and enable the Mcrypt extension.'
);
$this->addChamiloRequirement(
class_exists('Locale'),
'intl extension should be available',
'Install and enable the intl extension.'
);
$this->addChamiloRequirement(
null !== $icuVersion && version_compare(
$icuVersion,
self::REQUIRED_ICU_VERSION,
'>='
),
'icu library must be at least '.self::REQUIRED_ICU_VERSION,
'Install and enable the icu library at least '.self::REQUIRED_ICU_VERSION.' version'
);
$extensions = $this->getExtensions();
foreach ($extensions as $type) {
$isOptional = $type == 'optional' ? true : false;
foreach ($type as $extension => $url) {
if (extension_loaded($extension)) {
$this->addChamiloRequirement(
extension_loaded($extension),
"$extension extension should be available",
"Install and enable the $extension
extension.",
$isOptional
);
}
}
}
$this->addRecommendation(
class_exists('SoapClient'),
'SOAP extension should be installed (API calls)',
'Install and enable the SOAP extension.'
);
// Windows specific checks
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$this->addRecommendation(
function_exists('finfo_open'),
'finfo_open() should be available',
'Install and enable the Fileinfo extension.'
);
$this->addRecommendation(
class_exists('COM'),
'COM extension should be installed',
'Install and enable the COM extension.'
);
}
// Unix specific checks
if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
$this->addRequirement(
$this->checkFileNameLength(),
'Cache folder should not be inside encrypted directory',
'Move app/cache folder outside encrypted directory.'
);
}
// Web installer specific checks
if ('cli' !== PHP_SAPI) {
$output = $this->checkCliRequirements();
$requirement = new CliRequirement(
!$output,
'Requirements validation for PHP CLI',
'If you have multiple PHP versions installed, you need to configure CHAMILO_PHP_PATH variable with PHP binary path used by web server'
);
$requirement->setOutput($output);
$this->add($requirement);
}
$baseDir = realpath(__DIR__.'/..');
$mem = $this->getBytes(ini_get('memory_limit'));
$this->addPhpIniRequirement(
'memory_limit',
function ($cfgValue) use ($mem) {
return $mem >= 256 * 1024 * 1024 || -1 == $mem;
},
false,
'memory_limit should be at least 256M',
'Set the "memory_limit" setting in php.ini* to at least "256M".'
);
$this->addChamiloRequirement(
is_writable($baseDir.'/web/uploads'),
'web/uploads/ directory must be writable',
'Change the permissions of the "web/uploads/" directory so that the web server can write into it.'
);
$this->addChamiloRequirement(
is_writable($baseDir.'/web/assetic'),
'web/assetic/ directory must be writable',
'Change the permissions of the "web/assetic/" directory so that the web server can write into it.'
);
$this->addChamiloRequirement(
is_writable($baseDir.'/web/bundles'),
'web/bundles/ directory must be writable',
'Change the permissions of the "web/bundles/" directory so that the web server can write into it.'
);
/*$this->addChamiloRequirement(
is_writable($baseDir . '/web/media'),
'web/media/ directory must be writable',
'Change the permissions of the "web/media/" directory so that the web server can write into it.'
);
/*$this->addChamiloRequirement(
is_writable($baseDir . '/app/attachment'),
'app/attachment/ directory must be writable',
'Change the permissions of the "app/attachment/" directory so that the web server can write into it.'
);*/
if (is_dir($baseDir.'/web/js')) {
$this->addChamiloRequirement(
is_writable($baseDir.'/web/js'),
'web/js directory must be writable',
'Change the permissions of the "web/js" directory so that the web server can write into it.'
);
}
if (is_dir($baseDir.'/web/css')) {
$this->addChamiloRequirement(
is_writable($baseDir.'/web/css'),
'web/css directory must be writable',
'Change the permissions of the "web/css" directory so that the web server can write into it.'
);
}
if (!is_dir($baseDir.'/web/css') || !is_dir($baseDir.'/web/js')) {
$this->addChamiloRequirement(
is_writable($baseDir.'/web'),
'web directory must be writable',
'Change the permissions of the "web" directory so that the web server can write into it.'
);
}
if (is_file($baseDir.'/app/config/parameters.yml')) {
$this->addChamiloRequirement(
is_writable($baseDir.'/app/config/parameters.yml'),
'app/config/parameters.yml file must be writable',
'Change the permissions of the "app/config/parameters.yml" file so that the web server can write into it.'
);
}
}
/**
* @return array
*/
private function getExtensions()
{
return
array(
'required' => array(
'mysql' => array('url' => 'http://php.net/manual/en/book.mysql.php'),
'curl' => array('url' => 'http://php.net/manual/fr/book.curl.php'),
'zlib' => array('url' => 'http://php.net/manual/en/book.zlib.php'),
'pcre' => array('url' => 'http://php.net/manual/en/book.pcre.php'),
'xml' => array('url' => 'http://php.net/manual/en/book.xml.php'),
'mbstring' => array('url' => 'http://php.net/manual/en/book.mbstring.php'),
'iconv' => array('url' => 'http://php.net/manual/en/book.iconv.php'),
'intl' => array('url' => 'http://php.net/manual/en/book.intl.php'),
'gd' => array('url' => 'http://php.net/manual/en/book.image.php'),
'json' => array('url' => 'http://php.net/manual/en/book.json.php'),
),
'optional' => array(
'imagick' => array('url' => 'http://php.net/manual/en/book.imagick.php'),
'ldap' => array('url' => 'http://php.net/manual/en/book.ldap.php'),
'xapian' => array('url' => 'http://php.net/manual/en/book.xapian.php'),
),
);
}
/**
* Adds an Chamilo specific requirement.
*
* @param boolean $fulfilled Whether the requirement is fulfilled
* @param string $testMessage The message for testing the requirement
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param bool $optional
*/
public function addChamiloRequirement(
$fulfilled,
$testMessage,
$helpHtml,
$helpText = null,
$optional = false
) {
$this->add(
new ChamiloRequirement(
$fulfilled,
$testMessage,
$helpHtml,
$helpText,
$optional
)
);
}
/**
* Get the list of mandatory requirements (all requirements excluding PhpIniRequirement)
*
* @return array
*/
public function getMandatoryRequirements()
{
return array_filter(
$this->getRequirements(),
function ($requirement) {
return !($requirement instanceof PhpIniRequirement)
&& !($requirement instanceof ChamiloRequirement)
&& !($requirement instanceof CliRequirement);
}
);
}
/**
* Get the list of PHP ini requirements
*
* @return array
*/
public function getPhpIniRequirements()
{
return array_filter(
$this->getRequirements(),
function ($requirement) {
return $requirement instanceof PhpIniRequirement;
}
);
}
/**
* Get the list of Chamilo specific requirements
*
* @return array
*/
public function getChamiloRequirements()
{
return array_filter(
$this->getRequirements(),
function ($requirement) {
return $requirement instanceof ChamiloRequirement;
}
);
}
/**
* @return array
*/
public function getCliRequirements()
{
return array_filter(
$this->getRequirements(),
function ($requirement) {
return $requirement instanceof CliRequirement;
}
);
}
/**
* @param string $val
* @return int
*/
protected function getBytes($val)
{
if (empty($val)) {
return 0;
}
preg_match('/([\-0-9]+)[\s]*([a-z]*)$/i', trim($val), $matches);
if (isset($matches[1])) {
$val = (int)$matches[1];
}
switch (strtolower($matches[2])) {
case 'g':
case 'gb':
$val *= 1024;
// no break
case 'm':
case 'mb':
$val *= 1024;
// no break
case 'k':
case 'kb':
$val *= 1024;
// no break
}
return (float)$val;
}
/**
* {@inheritdoc}
*/
public function getRequirements()
{
$requirements = parent::getRequirements();
foreach ($requirements as $key => $requirement) {
$testMessage = $requirement->getTestMessage();
if (preg_match_all(
self::EXCLUDE_REQUIREMENTS_MASK,
$testMessage,
$matches
)) {
unset($requirements[$key]);
}
}
return $requirements;
}
/**
* {@inheritdoc}
*/
public function getRecommendations()
{
$recommendations = parent::getRecommendations();
foreach ($recommendations as $key => $recommendation) {
$testMessage = $recommendation->getTestMessage();
if (preg_match_all(
self::EXCLUDE_REQUIREMENTS_MASK,
$testMessage,
$matches
)) {
unset($recommendations[$key]);
}
}
return $recommendations;
}
/**
* @return bool
*/
protected function checkNodeExists()
{
$nodeExists = new ProcessBuilder(array('node', '--version'));
$nodeExists = $nodeExists->getProcess();
if (isset($_SERVER['PATH'])) {
$nodeExists->setEnv(array('PATH' => $_SERVER['PATH']));
}
$nodeExists->run();
return $nodeExists->getErrorOutput() === null;
}
/**
* @return bool
*/
protected function checkFileNameLength()
{
$getConf = new ProcessBuilder(array('getconf', 'NAME_MAX', __DIR__));
$getConf = $getConf->getProcess();
if (isset($_SERVER['PATH'])) {
$getConf->setEnv(array('PATH' => $_SERVER['PATH']));
}
$getConf->run();
if ($getConf->getErrorOutput()) {
// getconf not installed
return true;
}
$fileLength = trim($getConf->getOutput());
return $fileLength == 255;
}
/**
* @return null|string
*/
protected function checkCliRequirements()
{
$finder = new PhpExecutableFinder();
$command = sprintf(
'%s %schamilo-check.php',
$finder->find(),
__DIR__.DIRECTORY_SEPARATOR
);
return shell_exec($command);
}
}
class ChamiloRequirement extends Requirement
{
}
class CliRequirement extends Requirement
{
/**
* @var string
*/
protected $output;
/**
* @return string
*/
public function getOutput()
{
return $this->output;
}
/**
* @param string $output
*/
public function setOutput($output)
{
$this->output = $output;
}
}