Source for file tangra_module_installer.class.php
Documentation is available at tangra_module_installer.class.php
// *** Tangra (Application Framework and Tools for PHP)
* Contains class Tangra_Module_Installer
* @subpackage modules_manager
require_once(TANGRA_MAIN_DIR. 'filesystem_toolbox/filesystem_functions.inc.php');
require_once(TANGRA_MAIN_DIR. 'filesystem_toolbox/tangra_file.class.php');
require_once(TANGRA_MAIN_DIR. 'core/tangra_simple_tple.class.php');
require_once(TANGRA_MAIN_DIR. 'modules_manager/can_upgrade_loader.class.php');
require_once(TANGRA_MAIN_DIR. 'misc/misc.inc.php');
require_once('exceptions/te_tmm_target_dir_not_exists.class.php');
require_once('exceptions/te_tmm_target_dir_not_writable.class.php');
require_once('exceptions/te_tmm_item_already_exist.class.php');
define('TMM_INSTALL_ITEM_TYPE_FILE', 0);
define('TMM_INSTALL_ITEM_TYPE_DIR', 1);
define('TMM_INSTALL_ITEM_TYPE_SYMLINK', 2);
* Prefix for section start in config file
define('TMM_CONFFILE_SECTION_START_PREFIX', "\n//+++ section ");
* Suffix for section start in config file
define('TMM_CONFFILE_SECTION_START_SUFFIX', " START\n\n");
* Prefix for section end in config file
define('TMM_CONFFILE_SECTION_END_PREFIX', "\n//--- section ");
* Suffix for section end in config file
define('TMM_CONFFILE_SECTION_END_SUFFIX', " END\n\n");
* Tangra_Module_Installer is the base class used by all module installers
* @subpackage modules_manager
* Root directory of the site where module will be installed
* List of installed files and directories
* Usergroup to which intalled files will be chown-ed
* Filepermissions that will be used to chmod installed files to
* Permissions that will be used to chmod dirs to
* Contains array with version => upgrade method pairs
* Each instance of module installer must provide values (in __constructor) here if it is capable of upgrade
* Parameter $params is a structured array that must have at least key 'target-path'. Other parameters have to be fed as key-value pairs.
* Example $params['smarty-dir'] = '/some/path';
* Activities that have to be performed before actual installation have to be placed here.
* Actual installation. This method have to be overwrited by inherited clases.
* Activities that have to be performed after actual installation have to be placed here.
* If you overwrite this method don't forget to call parent::post_install()
// $this->change_file_properties();
* Creates modules conf dir (hidden/conf/modules)
* Checks if all required parameters are present
* @throws TE_TMM_Exception
if (!$params['target-dir']) {
throw new TE_TMM_Exception('$params[target_dir] is empty.');
* @throws TE_TMM_Exception
if (ereg("^[a-z]{1}[a-z0-9_]{1,254}$", $name)) {
throw TE_TMM_Exception('Invalid module name: '. $name);
* @param string $module_dir
* Returns module source dir
* Sets root directory of the site where module will be installed
* @param string $target_dir
* @throws TE_TMM_Target_Dir_Not_Writable, TE_TMM_Target_Dir_Not_Exists, TE_TMM_Target_Dir_Not_Exists
throw new TE_TMM_Target_Dir_Not_Writable('Dir:'. $target_dir. ' is not writable');
throw new TE_TMM_Target_Dir_Not_Exists('Dir: '. $target_dir. '. Such item exist and it is not a directory.');
throw new TE_TMM_Target_Dir_Not_Exists('Target dir '. $target_dir. ' does not exist.');
* Gets root directory of the site where module will be installed
* Sets overwrite all flag
* Returns overwrite all flag
* Sets permission that will be used to chmod installed files to
* Please note that you have to pass parameter $file_permissions without leading zero (for octal value).
* @param integer $file_permissions
* Returns permission that will be used to chmod installed files to
* Sets permission that will be used to chmod installed dirs to
* Please note that you have to pass parameter $dir_permissions without leading zero (for octal value).
* @param integer $dir_permissions
* Returns permission that will be used to chmod installed dirs to
* Sets usergroup to which intalled files will be chown-ed
* @param string $file_group
* Returns usergroup to which intalled files will be chown-ed
* Checks if parameter is present
* @param string $parameter Parameter to be checked
* Recursive copy of given directory
* @param string $source_dir Source dir
* @param string $destination_dir destination dir
* @param boolean $is_root If false tries to create $destionation_dir if not already exist. If true will copy just the content of $source_dir.
* @throws TE_TMM_Exception
* Recursive copy of given directory (actual copy)
* @param string $source_dir Source dir
* @param string $destination_dir destination dir
* @param boolean $is_root If false tries to create $destionation_dir if not already exist. If true will copy just the content of $source_dir.
* @throws TE_TMM_Item_Already_Exist
while (($item = readdir($dir)) !== false) {
if ($item != '.' && $item != '..') {
throw new TE_TMM_Item_Already_Exist("File/directory ". "$destination_dir$item already exists. Consider using option 'overwrite'.");
if (is_file("$source_dir/$item")) {
if (copy("$source_dir/$item","$destination_dir$item")) {
throw new TE_TMM_Item_Already_Exist("Can't copy $source_dir/$item to $destination_dir$item");
* Sets installed files list.
* @throws Tangra_Exception
throw new Tangra_Exception('$files is not an array.');
* Returns installed files list
* Writes installed files list to files.list
foreach($this->files as $item) {
$str = $item['item']. ' '. $item['checksum']. "\n";
$str = $item['item']. "\n";
$file_list_itself = '%HIDDEN%conf/modules/'. $this->get_module_name(). '/files.list';
$file->write($file_list_itself. "\n");
* Sets file/dirs permissions and group (if values available)
* @param string $item Path to file / dir
if ($file_group || $file_perm || $dir_perm) {
if (is_dir($item) && $dir_perm) {
if (is_file($item) && $file_perm) {
$rez = @chgrp($item, $file_group);
* @param string $source_file Path to source file relative to module source dir
* @param string $target_file Path to target file relative to site target path
* @param boolean $special_file Flags file that will not be overwrited if just 'overwrite' flag is set. Such files are for example configuration files that you don't want to get overwrited when preinstalling module. If you want to overwrite special files use 'overwrite-all' flag.
* @throws TE_TMM_Exception,TE_TMM_Item_Already_Exist
protected function copy_static_file($source_file, $target_file, $special_file = false) {
throw new TE_TMM_Item_Already_Exist("Target file ". $this->get_target_dir(). $target_file. " exists. Consider using overwrite option.");
throw new TE_TMM_Exception("Source is not a file: ". $this->get_module_dir(). 'static/'. $source_file);
throw new TE_TMM_Exception("Can't find source file: ". $this->get_module_dir(). 'static/'. $source_file);
* @param string $source_file
* @param string $target_file
* @throws TE_TMM_Exception
throw new TE_TMM_Exception("Can't copy $source_file to ". $this->get_target_dir(). $target_file);
* Creates module's config dir, i.e. where module.ctrl file will be installed
* @param string $modules_conf_dir
* Creates directory and adds it to files list.
* If directory already exists is just added to files list.
* @param string $dir Directory to be created. Relative to target_path
* @throws TE_TMM_Exception
throw new TE_TMM_Exception('Can not create dir: '. $dir);
* Creates directory and adds it to files list.
* If directory already exists is just added to files list.
* @param string $dir Directory to be created specified with full path
throw new TE_TMM_Exception('Can not create dir: '. $dir);
* Compiles template file and writes the rezult in destination file. Adds full destination path to files list.
* @param Tangra_Simple_Tple $tple Template engine object with preassigned values that will be substituted
* @param string $file Temlate file
* @param string $destination_file Destination file
* @param boolean $special_file Flags file that will not be overwrited if just 'overwrite' flag is set. Such files are for example configuration files that you don't want to get overwrited when preinstalling module. If you want to overwrite special files use 'overwrite-all' flag.
* @throws TE_TMM_Item_Already_Exist
protected function compile_tpl_file(Tangra_Simple_Tple $tple, $file, $destination_file, $special_file = false) {
throw new TE_TMM_Item_Already_Exist("Target file ". $this->get_target_dir(). $destination_file. " exists. Consider using overwrite parameter.");
* Actual compilation of template file
* @see compile_tpl_file()
* @param Tangra_Simple_Tple $tple
* @param string $destination_file
* @throws TE_TMM_Exception
private function _compile_tpl_file(Tangra_Simple_Tple $tple, $file, $destination_file) {
$content = $tple->fetch($file);
throw new TE_TMM_Exception('Failed to create compiled file: '. $this->get_target_dir(). $destination_file);
* Creates symlink and adds it to files list
* @param string $source_file Source file that symlink will point to
* @param string $link_name Link name
* @param string $alternative_source_for_copy If symlinks are not available (like in Windows), just copy this file instead of creating symlink
* @throws TE_TMM_Exception,TE_TMM_Item_Already_Exist
protected function create_sym_link($source_file, $link_name, $alternative_source_for_copy = '') {
throw new TE_TMM_Exception('Unable to create symlink because dir with same name exists: '. $this->get_target_dir(). $link_name);
throw new TE_TMM_Item_Already_Exist("File/directory ". $this->get_target_dir(). $link_name. " already exists. Consider using option 'overwrite'.");
if ($alternative_source_for_copy) {
throw new TE_TMM_Exception('Failed to create file: '. $this->get_target_dir(). $link_name);
* Enter description here...
* @param string $source_file
* @param string $link_name
* @throws TE_TMM_Exception
throw new TE_TMM_Exception('Failed to create symlink: '. $this->get_target_dir(). $link_name);
* Copies module.ctrl file to modules conf dir
* @throws TE_TMM_Exception
* Adds new section to conf file
* @param string $file Path to config file relative to site target dir
* @param string $section_content Content of the section
* @param boolean $strict If true will throw exception if section already exists.
* @throws TE_TMM_Exception
throw new TE_TMM_Exception('Configuration section for module "'. $this->get_module_name(). '" already exist starting at: '. $boundaries['start']);
throw new TE_TMM_Exception('Configuration file does not exists: '. $this->get_target_dir(). $file);
* Actual adding of section to conf file
* @param string $full_path Full path to conf file
* @param string $section_content Content of the section
* Removes module section from conf file
* @param string $file Path to conh file relative to site target dir
* @param boolean $strict If true will throw exception if section does not exists.
* @throws TE_TMM_Exception
for ($i = $boundaries['start']; $i <= $boundaries['end']; $i++ ) {
throw new TE_TMM_Exception('Configuration section for module "'. $this->get_module_name(). '" does not exist.');
throw new TE_TMM_Exception('Configuration file does not exists: '. $this->get_target_dir(). $file);
* Find start and end indexes of module's section
* @return array Structured array 'start' => start index, 'end' => end index
for ($i = 0; $i < count($arr); $i++ ) {
if (strpos($arr[$i], trim($start_tag)) !== false) {
if ($start_found !== false) {
for ($i = $start_found; $i < count($arr); $i++ ) {
if ($start_found !== false && $end_found !== false) {
$ret['start'] = $start_found;
$ret['end'] = $end_found;
// * Changes file permisssions and groups
// * @see set_file_permissions(), set_file_group()
// private function change_file_properties() {
// $file_perm = $this->get_file_permissions();
// $dir_perm = $this->get_dir_permissions();
// $file_group = $this->get_file_group();
// if ($file_group || $file_perm || $dir_perm) {
// foreach($this->files as $item) {
// if (is_file($item['item']) || is_link($item['item'])) {
// $rez = @chmod($item['item'], octdec('0'.$file_perm));
// if (is_dir($item['item'])) {
// $rez = @chmod($item['item'], octdec('0'.$dir_perm));
// $rez = @chgrp($item['item'], $file_group);
* Deinstallation of the module
* Incomplete method. TCC has functionality to remove modules.
* Adds file to files list
* @param string $item Full path to the file
* @param string $item Full path to the dir
* Adds symlink to files list
* @param string $item Full path to the symlink
* Converts full path to abstract path, this way files.list is portable between depoyments
* This method accepts $item like /var/www/sites/test/hidden/inc/classes/some_class.class.php and converts it to %HIDDEN%inc/classes/some_class.class.php
* @param string $item Full path of a item
* @return string abstracted path
$item = str_replace($target_dir. 'hidden/', '%HIDDEN%', $item);
$item = str_replace($target_dir. 'htdocs/', '%HTDOCS%', $item);
$item = str_replace($target_dir. 'ext_inc/', '%EXT_INC%', $item);
$item = str_replace($target_dir. 'scratch/', '%SCRATCH%', $item);
* Compiles bulk of files contained in $source_dir into $destination_dir
* @param Tangra_Simple_Tple $tple Tangra_Simple_Tple instance. You have to set all exports before calling this method
* @param string $source_dir Relative to $tple->get_tpl_path(). Example: 'htdocs'
* @param string $destination_dir Relative to $this->get_target_dir(). Example: 'htdocs/admin'
* @param boolean $is_root If false tries to create $destionation_dir if not already exist. If true will copy just the content of $source_dir.
protected function compile_bulk(Tangra_Simple_Tple $tple, $source_dir, $destination_dir, $is_root = true) {
$source_dir = $tple->get_tpl_path(). $source_dir;
$this->_compile_bulk($tple, $source_dir, $destination_dir, $is_root);
* Actual compilation of bulk files. See compile_bulk();
* This method is not ment to be called directly by the user. Use compile_bulk() instead.
* @param Tangra_Simple_Tple $tple Tangra_Simple_Tple instance. You have to set all exports before calling this method
* @param string $source_dir Relative to $tple->get_tpl_path(). Example: 'htdocs'
* @param string $destination_dir Relative to $this->get_target_dir(). Example: 'htdocs/admin'
* @param boolean $is_root If false tries to create $destionation_dir if not already exist. If true will copy just the content of $source_dir.
* @throws TE_TMM_Item_Already_Exist,TE_TMM_Exception
private function _compile_bulk(Tangra_Simple_Tple $tple, $source_dir, $destination_dir, $is_root = true) {
throw new TE_TMM_Exception("Can't create dir $destination_dir/$item");
while (($item = readdir($dir)) !== false) {
if ($item != '.' && $item != '..') {
throw new TE_TMM_Item_Already_Exist("File ". "$destination_dir$item already exists. Consider using option 'overwrite'.");
if (is_file("$source_dir/$item")) {
throw new TE_TMM_Exception("Can't compile $source_dir/$item to $destination_dir$item");
* This function is called to check if installer can upgrade from given version.
* @param string $from_version
* Activities that have to be performed before actual upgrade have to be placed here.
* If you overwrite this method don't forget to call parent::pre_upgrade()
* @param string $from_version
* Makes a copy of current files.list in order to be used later when generating new one (after upgrade)
* @param string $from_version
$files_list_path = $module_conf_dir. 'files.list';
$files_list_old = $module_conf_dir. 'files.list.'. $from_version;
$rez = @copy($files_list_path, $files_list_old);
throw new TE_TMM_Exception('Cannot copy '. $files_list_path. ' to '. $files_list_old);
* Performs upgrade of module
* @param string $from_version
public function upgrade($from_version) {
$this->$method_name($from_version);
* Activities that have to be performed after actual upgrade have to be placed here.
* If you overwrite this method don't forget to call parent::post_upgrade()
* @param string $from_version
* Adds new class method that will handle upgrade from particular version
* @param string $method_name
throw new TE_TMM_Exception("Method $method_name does not exist");
* Returns name of the method that will perform upgrade from version $from_version
* Name of the metod is lookup in $this->upgrade_matrix
* @param string $from_version
$arr = $can_upgrade_loader->get_can_upgrade();
foreach($arr as $version => $method) {
global $ERROR_REPORTING_PHP4_LIBS;
|