| Server IP : 103.161.17.216 / Your IP : 216.73.216.1 Web Server : nginx/1.18.0 System : Linux tipsysaigoncharming 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 User : www-data ( 33) PHP Version : 7.4.3-4ubuntu2.29 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/app.houseland.info/application/libraries/ |
Upload File : |
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class App_modules
{
/**
* @since 2.3.4
*
* There is function add_module_support($module_name, $feature) so modules can hook support
* Check the function add_module_support for more info
*
* @var array
*/
private static $supports = [];
private $ci;
/**
* The modules info that is stored in database
* @var array
*/
private $db_modules = [];
/**
* All valid modules
* @var array
*/
private $modules = [];
/**
* All activated modules
* @var array
*/
private $active_modules = [];
/**
* Module new version data
* @var array
*/
private $new_version_data = [];
public function __construct()
{
$this->ci = &get_instance();
$this->ci->load->helper('directory');
/**
* The modules feature is added in version 2.3.0 if the current database version is smaller don't try to load the modules
* This code exists because after update, the database is not yet updated and the table modules does not exists and will throw errors.
*/
if ($this->ci->app->get_current_db_version() < 230) {
return;
}
$this->initialize();
}
/**
* Activate Module
* @param string $name Module Name [system_name]
* @return boolean
*/
public function activate($name)
{
$module = $this->get($name);
if (!$module) {
return false;
}
/**
* Check if module is already added to database
*/
if (!$this->module_exists_in_database($name)) {
$this->ci->db->where('module_name', $name);
$this->ci->db->insert(db_prefix() . 'modules', ['module_name' => $name, 'installed_version' => $module['headers']['version']]);
}
include_once($module['init_file']);
/**
* Maybe used from another modules?
*/
hooks()->do_action('pre_activate_module', $module);
/**
* Module developers can add hooks for their own activate actions that needs to be taken
*/
hooks()->do_action("activate_{$name}_module");
/**
* Activate the module in database
*/
$this->ci->db->where('module_name', $name);
$this->ci->db->update(db_prefix() . 'modules', ['active' => 1]);
/**
* After module is activated action
*/
hooks()->do_action('module_activated', $module);
return true;
}
/**
* Deactivate Module
* @param string $name Module Name [system_name]
* @return boolean
*/
public function deactivate($name)
{
$module = $this->get($name);
if (!$module) {
return false;
}
/**
* Maybe used from another modules?
*/
hooks()->do_action('pre_deactivate_module', $module);
/**
* Module developers can add hooks for their own activate actions that needs to be taken
*/
hooks()->do_action("deactivate_{$name}_module");
/**
* Deactivate the module in database
*/
$this->ci->db->where('module_name', $name);
$this->ci->db->update(db_prefix() . 'modules', ['active' => 0]);
/**
* After module is activated action
*/
hooks()->do_action('module_deactivated', $module);
return true;
}
/**
* Uninstall Module
* @param string $name Module Name [system_name]
* @return boolean
*/
public function uninstall($name)
{
$module = $this->get($name);
if (!$module) {
return false;
}
/**
* Module needs to be deactivated first in order to be uninstalled
*/
if ($module['activated'] == 1 || in_array($name, uninstallable_modules())) {
return false;
}
/**
* Maybe used from another modules?
*/
hooks()->do_action('pre_uninstall_module', $module);
/**
* Remove the module from database
*/
$this->ci->db->where('module_name', $name);
$this->ci->db->delete(db_prefix() . 'modules');
/**
* Module developers can add hooks for their own uninstall actions that needs to be taken
*/
$uninstallPath = $module['path'] . 'uninstall.php';
if (file_exists($uninstallPath)) {
include_once($uninstallPath);
} else {
hooks()->do_action("uninstall_{$name}_module");
}
/**
* Delete module files
*/
if (is_dir($module['path'])) {
delete_files($module['path'], true);
rmdir($module['path']);
}
/**
* After module is uninstalled action
*/
hooks()->do_action('module_uninstalled', $module);
return true;
}
/**
* Get all activated modules
* @return array
*/
public function get_activated()
{
return $this->active_modules;
}
/**
* Check whether a module is active
* @param string $name module name
* @return boolean
*/
public function is_active($name)
{
return array_key_exists($name, $this->get_activated());
}
/**
* Check whether a module is inactive
* @param string $name module name
* @return boolean
*/
public function is_inactive($name)
{
return ! $this->is_active($name);
}
/**
* Check whether a module is installed for a first time
* @param string $name module name
* @return boolean
*/
public function is_installed($name)
{
if (!isset($this->modules[$name])) {
return false;
}
return $this->modules[$name]['installed_version'] !== false;
}
/**
* Check if the module minimum requirement version is met
* @param [type] $name [description]
* @return boolean [description]
*/
public function is_minimum_version_requirement_met($name)
{
$module = $this->get($name);
if (!isset($module['headers']['requires_at_least'])) {
return true;
}
$this->ci->config->load('migration');
$appVersion = wordwrap($this->ci->config->item('migration_version'), 1, '.', true);
$moduleRequiresAppVersion = $module['headers']['requires_at_least'];
if (version_compare($appVersion, $moduleRequiresAppVersion, '>=')) {
return true;
}
return false;
}
/**
* Upgrade module to latest database version
* @param string $name module name
* @return mixed
*/
public function upgrade_database($name)
{
$migration = new App_module_migration($name);
if ($migration->to_latest() === false) {
return $migration->error_string();
}
return true;
}
/**
* Check whether database upgrade is required to module
* When module Version header is different then the one stored in database
* @param string $name module name
* @return boolean
*/
public function is_database_upgrade_required($name)
{
$module = $this->get($name);
$moduleInstalledVersion = $module['installed_version'];
if ($moduleInstalledVersion == false) {
// Not yet activated for the first time
return false;
}
$moduleFilesVersion = $module['headers']['version'];
/**
* Check if downgrade is required
* By default, version_compare() returns -1 if the first version is lower than the second,
* 0 if they are equal, and 1 if the second is lower.
*/
if (version_compare($moduleInstalledVersion, $moduleFilesVersion) === 1) {
return true;
}
if (version_compare($moduleFilesVersion, $moduleInstalledVersion) === 1) {
return true;
}
return false;
}
/**
* Modules can create release_handler.php file inside the module root directory and apply their own logic to check whether there is new version available.
* release_handler.php file should return false if there is no version available or array with e.q. the following params:
* $data['version'] = VERSION_NUMBER;
* (Optional) $data['changelog'] = 'https://official-website.com/plugin/changelog';
* (Optional) $data['update_handler'] = '';
* @param string $name module system name
* @return mixed
*/
public function new_version_available($name)
{
$retVal = $this->get_new_version_data($name);
if ($retVal !== false && !is_array($retVal)) {
return false;
}
return $retVal;
}
public function get_new_version_data($name)
{
if (isset($this->new_version_data[$name])) {
return $this->new_version_data[$name];
}
$file = module_dir_path($name, 'release_handler.php');
if (!file_exists($file)) {
return false;
}
$retVal = include_once($file);
$this->new_version_data[$name] = $retVal;
if ($this->is_update_handler_available($name)) {
hooks()->add_action('module_' . $name . '_update_handler', $retVal['update_handler']);
}
return $retVal;
}
public function update_to_new_version($name)
{
$data = $this->get_new_version_data($name);
hooks()->do_action('module_' . $name . '_update_handler', $data['update_handler']);
}
public function is_update_handler_available($name)
{
$retVal = $this->get_new_version_data($name);
if (isset($retVal['update_handler']) && $retVal['update_handler']) {
return true;
}
return false;
}
/**
* Return the number of modules that requires database upgrade
* @return integer
*/
public function number_of_modules_that_require_database_upgrade()
{
$CI = &get_instance();
$cacheKey = 'no-of-modules-require-database-upgrade';
$total = $CI->app_object_cache->get($cacheKey);
if ($total === false) {
$total = 0;
foreach ($this->modules as $module) {
if ($this->is_database_upgrade_required($module['system_name'])) {
$total++;
}
}
$CI->app_object_cache->add($cacheKey, $total);
}
return $total;
}
/**
* Get all modules or specific module if module system name is passed
* This method returns all modules including active and inactive
* @param mixed $module
* @return mixed
*/
public function get($module = null)
{
if (!$module) {
$modules = $this->modules;
/* Sort modules by name */
usort($modules, function ($a, $b) {
return strcmp(strtolower($a['headers']['module_name']), strtolower($b['headers']['module_name']));
});
return $modules;
}
if (isset($this->modules[$module])) {
return $this->modules[$module];
}
return null;
}
/**
* Get module from database
* @param string $name module system name
* @return mixed
*/
public function get_database_module($name)
{
if (isset($this->db_modules[$name])) {
return $this->db_modules[$name];
}
$this->ci->db->where('module_name', $name);
return $this->ci->db->get(db_prefix() . 'modules')->row();
}
/**
* Initialize all modules
* @return null
*/
public function initialize()
{
// For caching
$this->query_db_modules();
foreach (static::get_valid_modules() as $module) {
$name = $module['name'];
// If the module hasn't already been added and isn't a file
if (!isset($this->modules[$name])) {
/**
* System name
*/
$this->modules[$name]['system_name'] = $name;
/**
* Module headers
*/
$this->modules[$name]['headers'] = $this->get_headers($module['init_file']);
/**
* Init file path
* The file name must be the same like the module folder name
*/
$this->modules[$name]['init_file'] = $module['init_file'];
/**
* Module path
*/
$this->modules[$name]['path'] = $module['path'];
// Check if module is activated
$moduleDB = $this->get_database_module($name);
if ($moduleDB && $moduleDB->active == 1) {
$this->modules[$name]['activated'] = 1;
// Add to active modules handler
$this->active_modules[$name] = $this->modules[$name];
} else {
$this->modules[$name]['activated'] = 0;
}
/**
* Installed version
*/
$this->modules[$name]['installed_version'] = $moduleDB ? $moduleDB->installed_version : false;
}
}
}
/**
* @since 2.3.4
* @see add_module_support function.
*
* @param string $module_name module name
* @param string $feature support feature
*
*/
public function add_supports_feature($module_name, $feature)
{
if (!isset(self::$supports[$module_name])) {
self::$supports[$module_name] = [];
}
if (in_array($feature, self::$supports[$module_name])) {
return;
}
self::$supports[$module_name][] = $feature;
}
/**
* @since 2.3.4
* @see add_module_support function.
*
* @param string $module_name module name
* @param string $feature support feature
* @return boolean
*/
public function supports_feature($module_name, $feature)
{
return isset(self::$supports[$module_name]) && in_array($feature, self::$supports[$module_name]);
}
/**
* Get module headers info
* @param string $module_source the module init file location
* @return array
*/
public function get_headers($module_source)
{
$module_data = read_file($module_source); // Read the module init file.
preg_match('|Module Name:(.*)$|mi', $module_data, $name);
preg_match('|Module URI:(.*)$|mi', $module_data, $uri);
preg_match('|Version:(.*)|i', $module_data, $version);
preg_match('|Description:(.*)$|mi', $module_data, $description);
preg_match('|Author:(.*)$|mi', $module_data, $author_name);
preg_match('|Author URI:(.*)$|mi', $module_data, $author_uri);
preg_match('|Requires at least:(.*)$|mi', $module_data, $requires_at_least);
$arr = [];
if (isset($name[1])) {
$arr['module_name'] = trim($name[1]);
}
if (isset($uri[1])) {
$arr['uri'] = trim($uri[1]);
}
if (isset($version[1])) {
$arr['version'] = trim($version[1]);
} else {
$arr['version'] = 0;
}
if (isset($description[1])) {
$arr['description'] = trim($description[1]);
}
if (isset($author_name[1])) {
$arr['author'] = trim($author_name[1]);
}
if (isset($author_uri[1])) {
$arr['author_uri'] = trim($author_uri[1]);
}
if (isset($requires_at_least[1])) {
$arr['requires_at_least'] = trim($requires_at_least[1]);
}
return $arr;
}
/**
* Check whether module is inserted into database table
* @param string $name module system name
* @return boolean
*/
private function module_exists_in_database($name)
{
return (bool) $this->get_database_module($name);
}
/**
* Get valid modules
* @return array
*/
public static function get_valid_modules()
{
/**
* Modules path
*
* APP_MODULES_PATH constant is defined in application/config/constants.php
*
* @var array
*/
$modules = directory_map(APP_MODULES_PATH, 1);
$valid_modules = [];
if ($modules) {
foreach ($modules as $name) {
$name = strtolower(trim($name));
/**
* Filename may be returned like chat/ or chat\ from the directory_map function
*/
foreach (['\\', '/'] as $trim) {
$name = rtrim($name, $trim);
}
// If the module hasn't already been added and isn't a file
if (!stripos($name, '.')) {
$module_path = APP_MODULES_PATH . $name . '/';
$init_file = $module_path . $name . '.php';
// Make sure a valid module file by the same name as the folder exists
if (file_exists($init_file)) {
$valid_modules[] = [
'init_file' => $init_file,
'name' => $name,
'path' => $module_path,
];
}
}
}
}
return $valid_modules;
}
private function query_db_modules()
{
$db_modules = $this->ci->db->get(db_prefix() . 'modules')->result();
foreach ($db_modules as $db_module) {
$this->db_modules[$db_module->module_name] = $db_module;
}
}
}