piotrpolak/pepiscms

View on GitHub
pepiscms/application/core/PEPISCMS_Loader.php

Summary

Maintainability
D
2 days
Test Coverage
<?php

/**
 * PepisCMS
 *
 * Simple content management system
 *
 * @package             PepisCMS
 * @author              Piotr Polak
 * @copyright           Copyright (c) 2007-2018, Piotr Polak
 * @license             See license.txt
 * @link                http://www.polak.ro/
 */

defined('BASEPATH') or exit('No direct script access allowed');

/**
 * Enhanced loader
 */
class PEPISCMS_Loader extends CI_Loader
{
    // Cache
    private $module_directory_cache = array();

    /**
     * Loads a theme, a function complementary to view
     *
     * @param string $path
     * @param array $vars
     * @param boolean $return
     * @return object
     */
    public function theme($path, $vars = array(), $return = false)
    {
        // In CodeIgniter < 3.1 _ci_prepare_view_vars was called _ci_object_to_array
        $ci_vars = $this->_ci_prepare_view_vars($vars);
        return $this->_ci_load(array(
                '_ci_path' => $path,
                '_ci_vars' => $ci_vars,
                '_ci_return' => $return)
        );
    }

    /**
     * Model Loader
     *
     * This function lets users load and instantiate models.
     *
     * @param    string|array    the name of the class
     * @param    string    name for the model
     * @param    bool    database connection
     * @param    bool $hardfail
     * @return    void
     */
    public function model($model, $name = '', $db_conn = false, $hardfail = true)
    {
        // Keep this redundancy
        $original_model = $model;
        $original_name = $name;
        $original_db_conn = $db_conn;

        $CI = &get_instance();

        if (isset($CI->modulerunner) && $CI->modulerunner->getRunningModuleName()) {
            if (is_array($model)) {
                foreach ($model as $babe) {
                    $this->model($babe);
                }
                return;
            }

            if ($model == '') {
                return;
            }

            // Is the model in a sub-folder? If so, parse out the filename and path.
            if (strpos($model, '/') === false) {
                $path = '';
            } else {
                $x = explode('/', $model);
                $model = end($x);
                unset($x[count($x) - 1]);
                $path = implode('/', $x) . '/';
            }

            if ($name == '') {
                $name = $model;
            }

            if (in_array($name, $this->_ci_models, true)) {
                return;
            }

            if (isset($CI->$name)) {
                show_error('The model name you are loading is the name of a resource that is already being used: ' . $name);
            }

            $running_module_name = $CI->modulerunner->getRunningModuleName();

            $model_path = false;
            $model_directories = array(
                $this->resolveModuleDirectory($running_module_name),
                INSTALLATIONPATH . 'application/'
            );

            $CI->load->library('ModulePathResolver');
            foreach ($model_directories as $_model_directory) {
                $model_path = $CI->modulepathresolver->getModelPathUsingBaseDir($running_module_name, $model, $_model_directory);
                if ($model_path) {
                    break;
                }
            }

            if ($model_path) {
                if ($db_conn !== false and !class_exists('CI_DB')) {
                    if ($db_conn === true) {
                        $db_conn = '';
                    }

                    $CI->load->database($db_conn, false, true);
                }

                if (!class_exists('CI_Model')) {
                    load_class('CI_Model', false);
                }

                require_once($model_path);

                $model_class_name = ucfirst($model);

                $CI->$name = new $model_class_name();

                $this->_ci_models[] = $model_class_name;

                return;
            }
        }

        $this->_model($original_model, $original_name, $original_db_conn, $hardfail);
    }

    /**
     * Original loader method with hardfail added
     *
     * @param $model
     * @param string $name
     * @param bool $db_conn
     * @param bool $hardfail
     */
    private function _model($model, $name = '', $db_conn = false, $hardfail = true)
    {
        if (is_array($model)) {
            foreach ($model as $babe) {
                $this->model($babe);
            }
            return;
        }

        if ($model == '') {
            return;
        }

        $path = '';

        // Is the model in a sub-folder? If so, parse out the filename and path.
        if (($last_slash = strrpos($model, '/')) !== false) {
            // The path is in front of the last slash
            $path = substr($model, 0, $last_slash + 1);

            // And the model name behind it
            $model = substr($model, $last_slash + 1);
        }

        if ($name == '') {
            $name = $model;
        }

        if (in_array($name, $this->_ci_models, true)) {
            return;
        }

        $CI = &get_instance();
        if (isset($CI->$name)) {
            show_error('The model name you are loading is the name of a resource that is already being used: ' . $name);
        }

        foreach ($this->_ci_model_paths as $mod_path) {
            if (!file_exists($mod_path . 'models/' . $path . $model . '.php')) {
                continue;
            }

            if ($db_conn !== false and !class_exists('CI_DB')) {
                if ($db_conn === true) {
                    $db_conn = '';
                }

                $CI->load->database($db_conn, false, true);
            }

            if (!class_exists('CI_Model')) {
                load_class('Model', 'core');
            }

            require_once($mod_path . 'models/' . $path . $model . '.php');

            $model = ucfirst($model);

            $CI->$name = new $model();

            $this->_ci_models[] = $name;
            return;
        }

        if ($hardfail) {
            // couldn't find the model
            show_error('Unable to locate the model you have specified: ' . $model);
        }
    }

    /**
     * Loads config of the specified module. If the module param is not specified, it will load the config of the current module
     *
     * @param string $module_name
     */
    public function moduleConfig($module_name)
    {
        $CI = &get_instance();
        $CI->config->loadModuleConfig($module_name);
    }

    /**
     * Load module language.
     *
     * @param string $langfile
     * @param string|bool $idiom
     * @return bool
     */
    public function language($langfile, $idiom = false)
    {
        $CI = &get_instance();
        if (isset($CI->modulerunner) && ($module_name = $CI->modulerunner->getRunningModuleName())) {
            if ($CI->lang->loadForModule($langfile, $idiom, false, $module_name)) {
                return true;
            }
        }
        return $CI->lang->load($langfile, $idiom);
    }

    /**
     * Load module language
     *
     * @param string|bool $module_name
     * @param string|bool $langfile
     * @param string|bool $idiom
     * @return mixed
     */
    public function moduleLanguage($module_name = false, $langfile = false, $idiom = false)
    {
        if (!$idiom) {
            if (class_exists('Dispatcher') && ($d_lang = Dispatcher::getSiteLanguage())) {
                $idiom = $d_lang->ci_language;
            }
        }

        $CI = &get_instance();

        if (!$module_name && isset($CI->modulerunner)) {
            $module_name = $CI->modulerunner->getRunningModuleName();
        }

        if (!$langfile) {
            $langfile = $module_name;
        }

        return $CI->lang->loadForModule($langfile, $idiom, false, $module_name);
    }

    /**
     * Class Loader
     *
     * This function lets users load and instantiate classes.
     * It is designed to be called from a user's app controllers.
     *
     * @param string $library
     * @param null $params
     * @param null $object_name
     * @return bool|PEPISCMS_Loader|object
     */
    public function library($library = '', $params = null, $object_name = null)
    {
        if (empty($library)) {
            return $this;
        } elseif (is_array($library)) {
            foreach ($library as $key => $value) {
                if (is_int($key)) {
                    $this->library($value, $params);
                } else {
                    $this->library($key, $params, $value);
                }
            }

            return $this;
        }

        $CI = &get_instance();
        $isLoaded = false;
        if (isset($CI->modulerunner) && $CI->modulerunner->getRunningModuleName()) {
            $isLoaded = $this->moduleLibrary($CI->modulerunner->getRunningModuleName(), $library, $params);
        }
        if ($isLoaded) {
            return true;
        }
        return parent::library($library, $params, $object_name);
    }

    /**
     * Loads module library.
     *
     * @param string $module_name
     * @param string $library
     * @param mixed $params
     * @return bool|void
     */
    public function moduleLibrary($module_name, $library, $params = null)
    {
        if ($library == '') {
            return false;
        }

        if (!is_null($params) and !is_array($params)) {
            $params = null;
        }

        // Get the class name
        $class = str_replace('.php', '', trim($library, '/'));

        // We'll test for both lowercase and capitalized versions of the file name
        foreach (array(ucfirst($class), strtolower($class)) as $class) {
            $library_file_path = $this->resolveModuleDirectory($module_name) . 'libraries/' . $class . '.php';

            if (file_exists($library_file_path)) {
                // Safety:  Was the class already loaded by a previous call?
                if (in_array($library_file_path, $this->_ci_classes)) {
                    log_message('debug', $class . " class already loaded. Second attempt ignored.");
                    return;
                }

                include_once($library_file_path);
                $this->_ci_init_library($class, '', $params);
                return true;
            }
        } // END FOREACH
        return false;
    }

    /**
     * Loads module model.
     *
     * @param string $module_name
     * @param string $model
     * @param string $name
     * @param string|bool $db_conn
     */
    public function moduleModel($module_name, $model, $name = '', $db_conn = false)
    {
        $CI = &get_instance();
        $current_module_name = false;
        if (isset($CI->modulerunner)) {
            $current_module_name = $CI->modulerunner->getRunningModuleName();
        } else {
            $CI->load->library('ModuleRunner');
        }
        $CI->modulerunner->setRunningModuleName($module_name);
        $this->model($model, $name, $db_conn);
        $CI->modulerunner->setRunningModuleName($current_module_name);
    }

    /**
     * Tells whether the module is installed in user space
     * If it is in system space or does not exist the function will return false
     *
     * @param string $module_name
     * @return bool
     */
    public function isModuleInUserSpace($module_name)
    {
        $user_module_directory = INSTALLATIONPATH . 'modules/';

        return file_exists($user_module_directory . $module_name);
    }

    /**
     * Resolves module path
     * Priority: user space, core space
     *
     * @param string $module_name
     * @param boolean $web_path
     *
     * @return string|bool
     */
    public function resolveModuleDirectory($module_name, $web_path = false)
    {
        if (isset($this->module_directory_cache[$module_name][$web_path])) {
            // Some kind of runtime cache
            return $this->module_directory_cache[$module_name][$web_path];
        }

        $core_module_directory = APPPATH . '../modules/';
        $user_module_directory = INSTALLATIONPATH . 'modules/';

        if ($this->isModuleInUserSpace($module_name)) {
            if ($web_path){
                $module_directory = 'pepiscms/usermodules/';
            } else {
                $module_directory = $user_module_directory;
            }
        } elseif (file_exists($core_module_directory . $module_name)) {
            if ($web_path) {
                $module_directory = 'pepiscms/modules/';
            } else {
                $module_directory = $core_module_directory;
            }
        } else {
            $this->module_directory_cache[$module_name][$web_path] = false;
            return false;
        }

        $this->module_directory_cache[$module_name][$web_path] = $module_directory . $module_name . '/';
        return $this->module_directory_cache[$module_name][$web_path];
    }
}