Find the path to a module's file.
public static file_path ( $module = null, $folder = null, $file = null ) : string | ||
$module | string The name of the module to find. | |
$folder | string The folder within the module to search for the file (ie. controllers). | |
$file | string The name of the file to search for. | |
return | string | The full path to the file. |
/** * Triggers an individual event. * * NOTE: The payload sent to the event method is a pointer to the actual data. * This means that any operations on the data will affect the original data. * Use with care. * * @param string $event_name A string with the name of the event to trigger. Case sensitive. * @param mixed $payload (optional) A variable pointer to send to the event method. * * @return void */ public static function trigger($event_name = null, &$payload = null) { if (empty($event_name) || !is_string($event_name) || !array_key_exists($event_name, self::$events)) { return; } foreach (self::$events[$event_name] as $subscriber) { if (strpos($subscriber['filename'], '.php') === false) { $subscriber['filename'] .= '.php'; } $file_path = Modules::file_path($subscriber['module'], $subscriber['filepath'], $subscriber['filename']); if (!file_exists($file_path)) { continue; } @(include_once $file_path); if (!class_exists($subscriber['class'])) { // if class doesn't exist check that the function is callable // could be just a helper function if (is_callable($subscriber['method'])) { call_user_func($subscriber['method'], $payload); } continue; } $class = new $subscriber['class'](); if (!is_callable(array($class, $subscriber['method']))) { unset($class); continue; } $class->{$subscriber['method']}($payload); unset($class); } }
/** * Return an array of configuration settings from a single config file. * * @param string $file The config file to read. * @param boolean $failGracefully Whether to show errors or simply return false. * @param string $module Name of the module where the config file exists. * @param boolean $moduleOnly Whether to fail if config does not exist in * module directory. * * @return array An array of settings, or false on failure (if $failGracefully * is true). */ function read_config($file, $failGracefully = true, $module = '', $moduleOnly = false) { $file = $file == '' ? 'config' : str_replace('.php', '', $file); // Look in module first $found = false; if ($module) { $fileDetails = Modules::file_path($module, 'config', "{$file}.php"); if (!empty($fileDetails)) { $file = str_replace('.php', '', $fileDetails); $found = true; } } // Fall back to application directory if (!$found && !$moduleOnly) { $checkLocations = array(); if (defined('ENVIRONMENT')) { $checkLocations[] = APPPATH . 'config/' . ENVIRONMENT . "/{$file}"; } $checkLocations[] = APPPATH . "config/{$file}"; foreach ($checkLocations as $location) { if (file_exists($location . '.php')) { $file = $location; $found = true; break; } } } if (!$found) { if ($failGracefully === true) { return false; } show_error("The configuration file {$file}.php does not exist."); } include $file . '.php'; if (!isset($config) || !is_array($config)) { if ($failGracefully === true) { return false; } show_error("Your {$file}.php file does not appear to contain a valid configuration array."); } return $config; }
/** * Returns the 'module_config' array from a modules config/config.php file. * * The 'module_config' contains more information about a module, and even * provides enhanced features within the UI. All fields are optional. * * @author Liam Rutherford (http://www.liamr.com) * * <code> * $config['module_config'] = array( * 'name' => 'Blog', // The name that is displayed in the UI * 'description' => 'Simple Blog', // May appear at various places within the UI * 'author' => 'Your Name', // The name of the module's author * 'homepage' => 'http://...', // The module's home on the web * 'version' => '1.0.1', // Currently installed version * 'menu' => array( // A view file containing an <ul> that will be the sub-menu in the main nav. * 'context' => 'path/to/view' * ) * ); * </code> * * @param $module_name string The name of the module. * @param $return_full boolean Ignored if the 'module_config' portion exists. * Otherwise, if true, will return the entire config array, else an empty array * is returned. * * @return array An array of config settings, or an empty array. */ public static function config($module_name = null, $return_full = false) { // Get the path of the file and determine whether it exists. $config_file = Modules::file_path($module_name, 'config', 'config.php'); if (!file_exists($config_file)) { return array(); } // Include the file and determine whether it contains a config array. include $config_file; if (!isset($config)) { return array(); } // Check for the optional module_config and serialize if exists. if (isset($config['module_config'])) { return $config['module_config']; } elseif ($return_full === true && is_array($config)) { // If 'module_config' did not exist, $return_full is true, and $config // is an array, return it. return $config; } // 'module_config' was not found and either $return_full is false or $config // was not an array. return array(); }
/** * Save a language file * * @param string $filename The name of the file to locate. The file will be found by looking in all modules. * @param string $language The language to retrieve. * @param array $settings An array of the language settings * @param bool $return TRUE to return the contents or FALSE to write to file * @param bool $allowNewValues if true, new values can be added to the file * * @return mixed A string when the $return setting is true */ function save_lang_file($filename = null, $language = 'english', $settings = null, $return = false, $allowNewValues = false) { if (empty($filename) || !is_array($settings)) { return false; } // Is it a application lang file? Use the English folder to determine. $arFiles = scandir(APPPATH . "language/english/"); if ($filename == 'application_lang.php' || in_array($filename, $arFiles)) { $orig_path = APPPATH . "language/english/{$filename}"; $path = APPPATH . "language/{$language}/{$filename}"; } else { $module = str_replace('_lang.php', '', $filename); $orig_path = Modules::file_path($module, 'language', "english/{$filename}"); $path = Modules::file_path($module, 'language', "{$language}/{$filename}"); // If it's still empty, grab the module path if (empty($path)) { $path = Modules::path($module, 'language'); } } // Load the file and loop through the lines if (!is_file($orig_path)) { return false; } $contents = file_get_contents($orig_path); $contents = trim($contents) . "\n"; if (!is_file($path)) { // Create the folder... $folder = basename($path) == 'language' ? "{$path}/{$language}" : dirname($path); if (!is_dir($folder)) { mkdir($folder); $path = basename($path) == 'language' ? "{$folder}/{$module}_lang.php" : $path; } } // Save the file. foreach ($settings as $name => $val) { if ($val !== '') { $val = '\'' . addcslashes($val, '\'\\') . '\''; } // Use strrpos() instead of strpos() so we don't lose data when // people have put duplicate keys in the english files $start = strrpos($contents, '$lang[\'' . $name . '\']'); if ($start === false) { // Tried to add non-existent value? if ($allowNewValues && $val !== '') { $contents .= "\n\$lang['{$name}'] = {$val};"; continue; } else { return false; } } $end = strpos($contents, "\n", $start) + strlen("\n"); if ($val !== '') { $replace = '$lang[\'' . $name . '\'] = ' . $val . ";\n"; } else { $replace = '// ' . substr($contents, $start, $end - $start); } $contents = substr($contents, 0, $start) . $replace . substr($contents, $end); } // Is the produced code OK? if (!is_null(eval(str_replace('<?php', '', $contents)))) { return false; } // Make sure the file still has the php opening header in it... if (strpos($contents, '<?php') === false) { $contents = "<?php defined('BASEPATH') || exit('No direct script access allowed');\n\n{$contents}"; } if ($return) { return $contents; } // Write the changes out... if (!function_exists('write_file')) { $CI = get_instance(); $CI->load->helper('file'); } if (write_file($path, $contents)) { return true; } return false; }
/** * Finds the path to a module's file. * * @deprecated since 0.7.1 Use Modules::file_path() instead. * * @param $module string The name of the module to find. * @param $folder string The folder within the module to search for the file (ie. controllers). * @param $file string The name of the file to search for. * * @return string The full path to the file. */ function module_file_path($module = null, $folder = null, $file = null) { return Modules::file_path($module, $folder, $file); }
/** * Locates file by looping through the active and default themes, then the assets * folder (as specified in the config file). * * Files are searched for in this order... * 1 - active_theme/ * 2 - active_theme/type/ * 3 - default_theme/ * 4 - default_theme/type/ * 5 - asset_base/type * * Where 'type' is either 'css' or 'js'. * * If the file is not found, it is removed from the array. If the file is found, * a full url is created, using base_path(), unless the path already includes * 'http' at the beginning of the filename, in which case it is simply included * in the return files. * * For CSS files, if a script of the same name is found in both the default_theme * and the active_theme folders (or their type sub-folder), they are both returned, * with the default_theme linked to first, so that active_theme styles can override * those in the default_theme without having to recreate the entire stylesheet. * * @param array $files An array of file names to search for. * @param string $type Either 'css' or 'js'. * @param boolean $bypass_inheritance If true, will skip the check for parent * theme styles. * * @return array The complete list of files with url paths. */ private static function find_files($files = array(), $type = 'css', $bypass_inheritance = false) { // Grab the theme paths from the template library. $paths = Template::get('theme_paths'); $site_path = Template::get('site_path'); $active_theme = Template::get('active_theme'); $default_theme = Template::get('default_theme'); $new_files = array(); $clean_type = $type; $type = ".{$type}"; if (self::$debug) { echo "Active Theme = {$active_theme}<br/>\n Default Theme = {$default_theme}<br/>\n Site Path = {$site_path}<br/>\n File(s) to find: "; print_r($files); } // Check for HTTPS or HTTP connection $http_protocol = is_https() ? 'https' : 'http'; // Is the language moving right to left? $rtl = self::$rtl_postfix; $rtl_set = lang('bf_language_direction') == $rtl; foreach ($files as &$file) { // If it's an array, $file is css and has both 'file' and 'media' // keys. Store them for later use. if (is_array($file)) { if ($type == '.css') { $media = $file['media']; } $module = isset($file['module']) ? $file['module'] : ''; $file = $file['file']; } $file = (string) $file; // Strip out the file type for consistency // Using strripos and substr because rtrim was giving some odd // results (for instance, rtrim('tickets.js', '.js'); // would return 'ticket') $pos = strripos($file, $type); if ($pos !== false) { $file = substr($file, 0, $pos); } // If it contains an external URL, there's nothing more to do if (strpos($file, $http_protocol . ':') !== false || strpos($file, '//') === 0 || strpos($file, 'https:') !== false || strpos($file, 'http:') !== false) { $new_files[] = empty($media) ? $file : array('file' => $file, 'media' => $media); continue; } $found = false; // Non-module files if (empty($module)) { $media = empty($media) ? '' : $media; // Check all possible theme paths foreach ($paths as $path) { if (self::$debug) { echo "[Assets] Looking in:\n <ul>\n <li>{$site_path}{$path}/{$default_theme}{$file}{$type}</li>\n <li>{$site_path}{$path}/{$default_theme}{$clean_type}/{$file}{$type}</li>"; if (!empty($active_theme)) { echo "\n <li>{$site_path}{$path}/{$active_theme}{$file}{$type}</li>\n <li>{$site_path}{$path}/{$active_theme}{$clean_type}/{$file}{$type}</li>"; } echo "\n <li>{$site_path}" . self::$directories['base'] . "/{$clean_type}/{$file}{$type}</li>\n </ul>" . PHP_EOL; } // DEFAULT THEME // First, check the default theme. Add found files to the // array. Anything in the active theme will override it. // // If $default_theme and $active_theme are the same, // checking $default_theme would just repeat the // $active_theme section, resulting in duplicates if (!$bypass_inheritance && $default_theme !== $active_theme) { if ($file_array = self::get_file_array($site_path, "{$path}/{$default_theme}", $file, $type, $media)) { $new_files[] = $file_array; $found = true; } elseif ($file_array = self::get_file_array($site_path, "{$path}/{$default_theme}{$clean_type}/", $file, $type, $media)) { // If it wasn't in the root, check the $type sub-folder $new_files[] = $file_array; $found = true; } } // ACTIVE THEME // By grabbing a copy from both $default_theme and // $active_theme, simple CSS-only overrides for a theme are // supported, completely changing appearance through a // simple child CSS file if (!empty($active_theme)) { // separated this because the elseif below should not run if $active_theme is empty if ($file_array = self::get_file_array($site_path, "{$path}/{$active_theme}", $file, $type, $media)) { $new_files[] = $file_array; $found = true; } elseif ($file_array = self::get_file_array($site_path, "{$path}/{$active_theme}{$clean_type}/", $file, $type, $media)) { // If it wasn't in the root, check the $type sub-folder $new_files[] = $file_array; $found = true; } } // ASSET BASE // If the file hasn't been found, yet, look in the // 'assets.base_folder' if (!$found) { // Assets/type folder if ($file_array = self::get_file_array($site_path, self::$directories['base'] . "/{$clean_type}/", $file, $type, $media)) { $new_files[] = $file_array; } elseif ($file_array = self::get_file_array($site_path, self::$directories['base'] . '/', $file, $type, $media)) { // ASSETS ROOT // One last check to see if it's under assets without // the type sub-folder. Useful for keeping script // collections together $new_files[] = $file_array; } } // if (!$found) } // foreach ($paths as $path) } else { // Module Files $file_path_name = $file; // Try the /module/assets folder $path = Modules::file_path($module, self::$directories['base'], $file_path_name . $type); // If $path is empty, try the /module/assets/type folder if (empty($path)) { $file_path_name = "{$clean_type}/{$file}"; $path = Modules::file_path($module, self::$directories['base'], $file_path_name . $type); } // If the language is right-to-left, add -rtl to the file name if (!empty($path) && $rtl_set) { $path_rtl = Modules::file_path($module, self::$directories['base'], "{$file_path_name}-{$rtl}{$type}"); if (!empty($path_rtl)) { $path = $path_rtl; } } if (self::$debug) { echo "[Assets] Looking for MODULE asset at: {$path}<br/>" . PHP_EOL; } // If the file was found, add it to the array for output if (!empty($path)) { $file = array('file' => '', 'server_path' => $path); if (isset($media)) { $file['media'] = $media; } $new_files[] = $file; } } } //end foreach return $new_files; }
/** * Delete the data for a module * * Removes migration information, permissions based on the name of the * module, and any tables returned by the module's model's get_table() * method. * * @todo Use the migration library instead of doing everything directly. * * @param string $moduleName The name of the module * * @return bool true if the data is removed, false on error */ private function deleteModuleData($moduleName) { $this->load->dbforge(); $this->db->trans_begin(); // Drop the migration record - old Migration schema method $moduleNameLower = preg_replace("/[ -]/", "_", strtolower($moduleName)); if ($this->db->field_exists("{$moduleNameLower}_version", 'schema_version')) { $this->dbforge->drop_column('schema_version', "{$moduleNameLower}_version"); } // Drop the Migration record - new Migration schema method if ($this->db->field_exists('version', 'schema_version')) { $this->db->delete('schema_version', array('type' => $moduleNameLower . '_')); } // Get any permission ids $this->load->model('securinator/sec_permission_model'); $permissionKey = $this->sec_permission_model->get_key(); $permissionIds = $this->sec_permission_model->select($permissionKey)->like('name', $moduleName . '.', 'after')->find_all(); // Undo any permissions that exist, from the roles as well if (!empty($permissionIds)) { foreach ($permissionIds as $row) { $this->sec_permission_model->delete($row->permission_id); } } // Check whether there is a model to drop (a model should have a table // which may require dropping) $modelName = "{$moduleName}_model"; if (Modules::file_path($moduleName, 'models', "{$modelName}.php")) { // Drop the table $this->load->model("{$moduleName}/{$modelName}", 'mt'); $mtTableName = $this->mt->get_table(); // If the model has a table and it exists in the database, drop it if (!empty($mtTableName) && $this->db->table_exists($mtTableName)) { $this->dbforge->drop_table($mtTableName); } } // Complete the database transaction or roll it back if ($this->db->trans_status() === false) { $this->db->trans_rollback(); return false; } $this->db->trans_commit(); return true; }
/** * Initialize the library with the configuration settings. * * @return void */ public function __construct($params = array()) { // Require the abstract Migration class for use by the migrations. require_once Modules::file_path('migrations', 'libraries', 'Migration.php'); $this->_ci =& get_instance(); $this->coreMigrationsPath = isset($params['migrations_path']) ? $params['migrations_path'] : BFPATH . 'migrations'; // Add trailing slash if not set if (substr($this->coreMigrationsPath, -1) != '/') { $this->coreMigrationsPath .= '/'; } // Sanity check if (!is_dir($this->coreMigrationsPath)) { $this->setError('Migrations Library is loaded but the migrations path is configured incorrectly, or the configured path is not a valid directory.'); show_error($this->getErrorMessage()); } // If the table is missing, create it if (!$this->createMigrationsTable(self::MAX_SCHEMA_VERSION)) { show_error($this->getErrorMessage()); } if (!is_array(self::$schemaVersion)) { self::$schemaVersion = array(); } }
/** * Save a language file. * * @param string $filename The name of the file to locate. The file will be * found by looking in the admin, main and all modules languages folders. * @param string $language The language to retrieve. * @param string $domain The domain where the language is located. * @param array $new_values An array of the language lines to replace. * @param boolean $return True to return the contents or false to write to * the file. * @param boolean $allow_new_values If true, new values can be added to the file. * * @return bool|string False if there was a problem loading the file. Otherwise, * returns true when $return is false or a string containing the file's contents * when $return is true. */ function save_lang_file($filename = NULL, $language = 'english', $domain = 'main', $new_values = array(), $return = FALSE, $allow_new_values = FALSE) { if (empty($filename) or !is_array($new_values)) { return FALSE; } // Is it a admin, main or module domain lang file? if (file_exists(ROOTPATH . "{$domain}/language/{$language}/{$filename}")) { $path = ROOTPATH . "{$domain}/language/{$language}/{$filename}"; } else { // Look in modules $module = str_replace('_lang.php', '', $filename); $path = Modules::file_path($module, 'language', "{$language}/{$filename}"); } // Load the file and loop through the lines if (!is_file($path)) { return FALSE; } $contents = file_get_contents($path); $contents = trim($contents) . "\n"; // Save the file. foreach ($new_values as $name => $val) { if ($val !== '') { $val = '\'' . addcslashes($val, '\'\\') . '\''; } // Use strrpos() instead of strpos() so we don't lose data when // people have put duplicate keys in the english files $start = strrpos($contents, '$lang[\'' . $name . '\']'); if ($start === FALSE) { // Tried to add non-existent value? if ($allow_new_values && $val !== '') { $contents .= "\n\$lang['{$name}'] = {$val};"; continue; } else { return FALSE; } } $end = strpos($contents, "\n", $start) + strlen("\n"); if ($val !== '') { $replace = '$lang[\'' . $name . '\'] = ' . $val . ";\n"; } else { $replace = '// ' . substr($contents, $start, $end - $start); } $contents = substr($contents, 0, $start) . $replace . substr($contents, $end); } // Is the produced code OK? if (!is_null(eval(str_replace('<?php', '', $contents)))) { return FALSE; } // Make sure the file still has the php opening header in it... if (strpos($contents, '<?php') === FALSE) { $contents = "<?php if ( ! defined('BASEPATH')) exit('No direct access allowed');\n\n{$contents}"; } if ($return) { return $contents; } // Write the changes out... if (!function_exists('write_file')) { get_instance()->load->helper('file'); } if (write_file($path, $contents)) { return TRUE; } return FALSE; }
/** * Returns the 'module_config' array from a modules config/config.php file. * The 'module_config' contains more information about a module, and even * provide enhanced features within the UI. All fields are optional. * * @author Liam Rutherford (http://www.liamr.com) * * <code> * $config['module_config'] = array( * 'name' => 'Blog', // The name that is displayed in the UI * 'description' => 'Simple Blog', // May appear at various places within the UI * 'author' => 'Your Name', // The name of the module's author * 'homepage' => 'http://...', // The module's home on the web * 'version' => '1.0.1', // Currently installed version * 'menu' => array( // A view file containing an <ul> that will be the sub-menu in the main nav. * 'context' => 'path/to/view' * ) * ); * </code> * * @param $module_name string The name of the module. * @param $return_full boolean If true, will return the entire config array. * If false, will return only the 'module_config' portion. * * @return array An array of config settings, or an empty array if empty/not * found. */ public static function config($module_name = null, $return_full = false) { $config_param = array(); $config_file = Modules::file_path($module_name, 'config', 'config.php'); if (file_exists($config_file)) { include $config_file; // Check for the optional module_config and serialize if exists. if (isset($config['module_config'])) { $config_param = $config['module_config']; } elseif ($return_full === true && isset($config) && is_array($config)) { $config_param = $config; } } return $config_param; }