tangra logo
   
[ class tree: tangra_lib ] [ index: tangra_lib ] [ all elements ]
 

Source for file tangra_module_installer.class.php

Documentation is available at tangra_module_installer.class.php

  1. <?php
  2. // *** Tangra (Application Framework and Tools for PHP)
  3. // $Id$
  4. //
  5.  
  6. /**
  7.  * Contains class Tangra_Module_Installer
  8.  *
  9.  * @package  tangra_lib
  10.  * @subpackage  modules_manager
  11.  */
  12.  
  13. /**
  14.  *
  15.  */
  16. require_once(TANGRA_MAIN_DIR.'filesystem_toolbox/filesystem_functions.inc.php');
  17. /**
  18.  *
  19.  */
  20. require_once(TANGRA_MAIN_DIR.'filesystem_toolbox/tangra_file.class.php');
  21. /**
  22.  *
  23.  */
  24. require_once(TANGRA_MAIN_DIR.'core/tangra_simple_tple.class.php');
  25. /**
  26.  *
  27.  */
  28. require_once(TANGRA_MAIN_DIR.'modules_manager/can_upgrade_loader.class.php');
  29. /**
  30.  *
  31.  */
  32. require_once(TANGRA_MAIN_DIR.'misc/misc.inc.php');
  33.  
  34.  
  35. /**
  36.  *
  37.  */
  38. require_once('exceptions/te_tmm_target_dir_not_exists.class.php');
  39. /**
  40.  *
  41.  */
  42. require_once('exceptions/te_tmm_target_dir_not_writable.class.php');
  43. /**
  44.  *
  45.  */
  46. require_once('exceptions/te_tmm_item_already_exist.class.php');
  47.  
  48. /**
  49.  * Type File
  50.  *
  51.  */
  52. define('TMM_INSTALL_ITEM_TYPE_FILE'0);
  53. /**
  54.  * Type directory
  55.  *
  56.  */
  57. define('TMM_INSTALL_ITEM_TYPE_DIR'1);
  58. /**
  59.  * Type symlink
  60.  *
  61.  */
  62. define('TMM_INSTALL_ITEM_TYPE_SYMLINK'2);
  63.  
  64.  
  65. /**
  66.  * Prefix for section start in config file
  67.  *
  68.  */
  69. define('TMM_CONFFILE_SECTION_START_PREFIX'"\n//+++ section ");
  70. /**
  71.  * Suffix for section start in config file
  72.  *
  73.  */
  74. define('TMM_CONFFILE_SECTION_START_SUFFIX'" START\n\n");
  75. /**
  76.  * Prefix for section end in config file
  77.  *
  78.  */
  79. define('TMM_CONFFILE_SECTION_END_PREFIX'"\n//--- section ");
  80. /**
  81.  * Suffix for section end in config file
  82.  *
  83.  */
  84. define('TMM_CONFFILE_SECTION_END_SUFFIX'" END\n\n");
  85.  
  86.  
  87. /**
  88.  * Tangra_Module_Installer is the base class used by all module installers
  89.  *
  90.  * @package  tangra_lib
  91.  * @subpackage  modules_manager
  92.  */
  93. abstract class Tangra_Module_Installer extends Tangra_Class {
  94.     /**
  95.      * Name of the module
  96.      *
  97.      * @var string 
  98.      * @internal
  99.      */
  100.     private $module_name;
  101.     /**
  102.      * Module source dir
  103.      *
  104.      * @var string 
  105.      * @internal
  106.      */
  107.     private $module_dir;
  108.     /**
  109.      * Root directory of the site where module will be installed
  110.      *
  111.      * @var string 
  112.      * @internal
  113.      */
  114.     private $target_dir;
  115.     /**
  116.      * List of installed files and directories
  117.      *
  118.      * @var array 
  119.      * @internal
  120.      */
  121.     protected $files = array();
  122.     /**
  123.      * Flag for overwrite all
  124.      *
  125.      * @var boolean 
  126.      * @internal
  127.      */
  128.     private $overwrite_all;
  129.     /**
  130.      * Flag for overwrite
  131.      *
  132.      * @var boolean 
  133.      * @internal
  134.      */
  135.     private $overwrite;
  136.     /**
  137.      * Usergroup to which intalled files will be chown-ed
  138.      *
  139.      * @var string 
  140.      * @internal
  141.      */
  142.     private $file_group = '';
  143.  
  144.     /**
  145.      * Filepermissions that will be used to chmod installed files to
  146.      *
  147.      * @var integer 
  148.      * @internal
  149.      */
  150.     private $file_permissions = '';
  151.  
  152.     /**
  153.      * Permissions that will be used to chmod dirs to
  154.      *
  155.      * @var integer 
  156.      */
  157.     private $dir_permissions = '';
  158.  
  159.     /**
  160.      * Contains array with version => upgrade method pairs
  161.      *
  162.      * Each instance of module installer must provide values (in __constructor) here if it is capable of upgrade
  163.      *
  164.      * @var array 
  165.      */
  166.     private $upgrade_matrix = array();
  167.  
  168.  
  169.     /**
  170.      * Constructor
  171.      *
  172.      * Parameter $params is a structured array that must have at least key 'target-path'. Other parameters have to be fed as key-value pairs.
  173.      *
  174.      * Example $params['smarty-dir'] = '/some/path';
  175.      *
  176.      * @param array $params 
  177.      */
  178.     function __construct($params{
  179.         $this->check_params($params);
  180.         $this->set_target_dir($params['target-path']);
  181.         if ($this->is_parameter_present($params'overwrite')) {
  182.             $this->set_overwrite($params['overwrite']);
  183.         }
  184.  
  185.         if ($this->is_parameter_present($params'overwrite-all')) {
  186.             $this->set_overwrite_all($params['overwrite-all']);
  187.         }
  188.  
  189.         if ($this->is_parameter_present($params'file-permissions')) {
  190.             $this->set_file_permissions($params['file-permissions']);
  191.         }
  192.  
  193.         if ($this->is_parameter_present($params'dir-permissions')) {
  194.             $this->set_dir_permissions($params['dir-permissions']);
  195.         }
  196.  
  197.         if ($this->is_parameter_present($params'file-group')) {
  198.             $this->set_file_group($params['file-group']);
  199.         }
  200.     }
  201.  
  202.  
  203.     /**
  204.      * Activities that have to be performed before actual installation have to be placed here.
  205.      *
  206.      */
  207.     abstract function pre_install();
  208.  
  209.     /**
  210.      * Actual installation. This method have to be overwrited by inherited clases.
  211.      *
  212.      */
  213.     public function install({
  214.         $this->create_module_conf_dir();
  215.     }
  216.  
  217.  
  218.     /**
  219.      * Activities that have to be performed after actual installation have to be placed here.
  220.      *
  221.      * If you overwrite this method don't forget to call parent::post_install()
  222.      */
  223.     public function post_install({
  224.         $this->copy_module_ctrl();
  225.         $this->write_files_list();
  226. //        $this->change_file_properties();
  227.     }
  228.  
  229.     /**
  230.      * Creates modules conf dir (hidden/conf/modules)
  231.      *
  232.      */
  233.     abstract protected function create_module_conf_dir();
  234.  
  235.  
  236.     /**
  237.      * Checks if all required parameters are present
  238.      *
  239.      * @param array $params 
  240.      * @throws TE_TMM_Exception
  241.      */
  242.     protected function check_params($params{
  243.         if (array_key_exists('target-dir'$params)) {
  244.             if (!$params['target-dir']{
  245.                 throw new TE_TMM_Exception('$params[target_dir] is empty.');
  246.             }
  247.         }
  248.     }
  249.  
  250.  
  251.     /**
  252.      * Sets module name
  253.      *
  254.      * @param string $name 
  255.      * @throws TE_TMM_Exception
  256.      */
  257.     final protected function set_module_name($name{
  258.         if (ereg("^[a-z]{1}[a-z0-9_]{1,254}$"$name)) {
  259.             $this->module_name = $name;
  260.         else {
  261.             throw TE_TMM_Exception('Invalid module name: '.$name);
  262.         }
  263.     }
  264.  
  265.  
  266.     /**
  267.      * Returns module name
  268.      *
  269.      * @return string 
  270.      */
  271.     final public function get_module_name({
  272.         return $this->module_name;
  273.     }
  274.  
  275.  
  276.     /**
  277.      * Sets module source dir
  278.      *
  279.      * @param string $module_dir 
  280.      */
  281.     final protected function set_module_dir($module_dir{
  282.         $this->module_dir = $module_dir;
  283.     }
  284.  
  285.  
  286.     /**
  287.      * Returns module source dir
  288.      *
  289.      * @return unknown 
  290.      */
  291.     final public function get_module_dir({
  292.         return $this->module_dir;
  293.     }
  294.  
  295.  
  296.     /**
  297.      * Sets root directory of the site where module will be installed
  298.      *
  299.      * @param string $target_dir 
  300.      * @throws TE_TMM_Target_Dir_Not_Writable, TE_TMM_Target_Dir_Not_Exists, TE_TMM_Target_Dir_Not_Exists
  301.      */
  302.     final protected function set_target_dir($target_dir{
  303.         if (file_exists($target_dir)) {
  304.             if (is_dir($target_dir)) {
  305.                 if (is_writable($target_dir)) {
  306.                     $this->target_dir = tangra_normalize_path($target_dir);
  307.                 else {
  308.                     throw new TE_TMM_Target_Dir_Not_Writable('Dir:'.$target_dir.' is not writable');
  309.                 }
  310.             else {
  311.                 throw new TE_TMM_Target_Dir_Not_Exists('Dir: '.$target_dir.'. Such item exist and it is not a directory.');
  312.             }
  313.         else {
  314.             throw new TE_TMM_Target_Dir_Not_Exists('Target dir '.$target_dir.' does not exist.');
  315.         }
  316.     }
  317.  
  318.  
  319.     /**
  320.      * Gets root directory of the site where module will be installed
  321.      *
  322.      * @return unknown 
  323.      */
  324.     final public function get_target_dir({
  325.         return $this->target_dir;
  326.     }
  327.  
  328.  
  329.     /**
  330.      * Sets overwrite flag
  331.      *
  332.      * @param boolean $owr 
  333.      */
  334.     final public function set_overwrite($owr{
  335.         $this->overwrite = $owr true false;
  336.     }
  337.  
  338.  
  339.     /**
  340.      * Returns overwrite flag
  341.      *
  342.      * @return boolean 
  343.      */
  344.     final public function get_overwrite({
  345.         $ret $this->overwrite || $this->overwrite_all;
  346.         return $ret;
  347.     }
  348.  
  349.  
  350.     /**
  351.      * Sets overwrite all flag
  352.      *
  353.      * @param boolean $owr 
  354.      */
  355.     final public function set_overwrite_all($owr{
  356.         $this->overwrite_all = $owr true false;
  357.     }
  358.  
  359.  
  360.     /**
  361.      * Returns overwrite all flag
  362.      *
  363.      * @return boolean 
  364.      */
  365.     final public function get_overwrite_all({
  366.         return $this->overwrite_all;
  367.     }
  368.  
  369.  
  370.     /**
  371.      * Sets permission that will be used to chmod installed files to
  372.      *
  373.      * Please note that you have to pass parameter $file_permissions without leading zero (for octal value).
  374.      *
  375.      * @param integer $file_permissions 
  376.      */
  377.     final public function set_file_permissions($file_permissions{
  378.         $this->file_permissions = $file_permissions;
  379.     }
  380.  
  381.  
  382.     /**
  383.      * Returns permission that will be used to chmod installed files to
  384.      *
  385.      * @return integer 
  386.      */
  387.     final public function get_file_permissions({
  388.         return $this->file_permissions;
  389.     }
  390.  
  391.  
  392.     /**
  393.      * Sets permission that will be used to chmod installed dirs to
  394.      *
  395.      * Please note that you have to pass parameter $dir_permissions without leading zero (for octal value).
  396.      *
  397.      * @param integer $dir_permissions 
  398.      */
  399.     final public function set_dir_permissions($dir_permissions{
  400.         $this->dir_permissions = $dir_permissions;
  401.     }
  402.  
  403.  
  404.     /**
  405.      * Returns permission that will be used to chmod installed dirs to
  406.      *
  407.      * @return integer 
  408.      */
  409.     final public function get_dir_permissions({
  410.         return $this->dir_permissions;
  411.     }
  412.  
  413.  
  414.     /**
  415.      * Sets usergroup to which intalled files will be chown-ed
  416.      *
  417.      * @param string $file_group 
  418.      */
  419.     final public function set_file_group($file_group{
  420.         $this->file_group = $file_group;
  421.     }
  422.  
  423.  
  424.     /**
  425.      * Returns usergroup to which intalled files will be chown-ed
  426.      *
  427.      * @return unknown 
  428.      */
  429.     final public function get_file_group({
  430.         return $this->file_group;
  431.     }
  432.  
  433.  
  434.     /**
  435.      * Checks if parameter is present
  436.      *
  437.      * @param array $params 
  438.      * @param string $parameter Parameter to be checked
  439.      * @return boolean 
  440.      */
  441.     protected function is_parameter_present($params$parameter{
  442.         return array_key_exists($parameter$params);
  443.     }
  444.  
  445.  
  446.     /**
  447.      * Recursive copy of given directory
  448.      *
  449.      * @param string $source_dir Source dir
  450.      * @param string $destination_dir destination dir
  451.      * @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.
  452.      * @throws TE_TMM_Exception
  453.      */
  454.     protected function copy_static_content_bulk($source_dir$destination_dir$is_root true{
  455.         $destination_dir tangra_normalize_path($this->get_target_dir().$destination_dir);
  456.         $source_dir $this->get_module_dir().'static/'.$source_dir;
  457.         $this->_copy_static_content_bulk($source_dir$destination_dir$is_root);
  458.     }
  459.  
  460.  
  461.     /**
  462.      * Recursive copy of given directory (actual copy)
  463.      *
  464.      * @param string $source_dir Source dir
  465.      * @param string $destination_dir destination dir
  466.      * @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.
  467.      * @throws TE_TMM_Item_Already_Exist
  468.      */
  469.     private function _copy_static_content_bulk($source_dir$destination_dir$is_root true{
  470.         if (!$is_root{
  471.             if (!file_exists($destination_dir)) {
  472.                 $this->create_dir_full_path($destination_dir);
  473.             }
  474.         }
  475.  
  476.         if ($dir opendir($source_dir)) {
  477.             while (($item readdir($dir)) !== false{
  478.                 if ($item != '.' && $item != '..'{
  479.                     if (file_exists("$destination_dir$item"&& !is_dir("$destination_dir$item")) {
  480.                         if (!$this->get_overwrite()) {
  481.                             throw new TE_TMM_Item_Already_Exist("File/directory "."$destination_dir$item already exists. Consider using option 'overwrite'.");
  482.                         }
  483.                     }
  484.  
  485.                     if (is_file("$source_dir/$item")) {
  486.                         if (copy("$source_dir/$item","$destination_dir$item")) {
  487.                             $this->add_to_files_list_file("$destination_dir$item");
  488.                         else {
  489.                             throw new TE_TMM_Item_Already_Exist("Can't copy $source_dir/$item to $destination_dir$item");
  490.                         }
  491.                     else {
  492.                         if ($item != '.svn'{
  493.                             $tmp_arr $this->_copy_static_content_bulk("$source_dir/$item"tangra_normalize_path($destination_dir).$item.'/'false);
  494.                         else {
  495.                             continue;
  496.                         }
  497.                     }
  498.                 }
  499.             }
  500.             closedir($dir);
  501.         }
  502.     }
  503.  
  504.  
  505.     /**
  506.      * Sets installed files list.
  507.      *
  508.      * @param array $files 
  509.      * @throws Tangra_Exception
  510.      */
  511.     public function set_files($files{
  512.         if (is_array($files)) {
  513.             $this->files = $files;
  514.         else {
  515.             throw new Tangra_Exception('$files is not an array.');
  516.         }
  517.     }
  518.  
  519.  
  520.     /**
  521.      * Returns installed files list
  522.      *
  523.      * @return unknown 
  524.      */
  525.     public function get_files({
  526.         return $ret;
  527.     }
  528.  
  529.  
  530.     /**
  531.      * Writes installed files list to files.list
  532.      *
  533.      */
  534.     protected function write_files_list({
  535.         $filename $this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/files.list';
  536.  
  537.         $file new Tangra_File($filename"w");
  538.  
  539.         foreach($this->files as $item{
  540.             if ($item['type'== TMM_INSTALL_ITEM_TYPE_FILE{
  541.                 $str $item['item'].' '.$item['checksum']."\n";
  542.             else {
  543.                 $str $item['item']."\n";
  544.             }
  545.             $file->write($str);
  546.         }
  547.  
  548.         $file_list_itself '%HIDDEN%conf/modules/'.$this->get_module_name().'/files.list';
  549.         $file->write($file_list_itself."\n");
  550.  
  551.         $file->close();
  552.         $this->set_item_permissions($filename);
  553.     }
  554.  
  555.  
  556.  
  557.     /**
  558.      * Sets file/dirs permissions and group (if values available)
  559.      *
  560.      * @param string $item Path to file / dir
  561.      */
  562.     protected function set_item_permissions($item{
  563.         $file_perm $this->get_file_permissions();
  564.         $dir_perm $this->get_dir_permissions();
  565.         $file_group $this->get_file_group();
  566.  
  567.         if ($file_group || $file_perm || $dir_perm{
  568.             if (is_dir($item&& $dir_perm{
  569.                 $rez @chmod($itemoctdec('0'.$dir_perm));
  570.             }
  571.  
  572.             if (is_file($item&& $file_perm{
  573.                 $rez @chmod($itemoctdec('0'.$file_perm));
  574.             }
  575.  
  576.             if ($file_group{
  577.                 $rez @chgrp($item$file_group);
  578.             }
  579.         }
  580.     }
  581.  
  582.  
  583.  
  584.     /**
  585.      * Copies file.
  586.      *
  587.      * @param string $source_file Path to source file relative to module source dir
  588.      * @param string $target_file Path to target file relative to site target path
  589.      * @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.
  590.      * @throws TE_TMM_Exception,TE_TMM_Item_Already_Exist
  591.      */
  592.     protected function copy_static_file($source_file$target_file$special_file false{
  593.         $ret false;
  594.  
  595.         if (file_exists($this->get_module_dir().'static/'.$source_file)) {
  596.             if (is_file($this->get_module_dir().'static/'.$source_file)) {
  597.                 if (file_exists($this->get_target_dir().$target_file)) {
  598.                     if (!$special_file{
  599.                         if ($this->get_overwrite()) {
  600.                             $ret $this->_copy_static_file($source_file$target_file);
  601.                         else {
  602.                             throw new TE_TMM_Item_Already_Exist("Target file ".$this->get_target_dir().$target_file." exists. Consider using overwrite option.");
  603.                         }
  604.                     else {
  605.                         if ($this->get_overwrite_all()) {
  606.                             $ret $this->_copy_static_file($source_file$target_file);
  607.                         else {
  608.                             $this->add_to_files_list_file($this->get_target_dir().$target_file);
  609.                         }
  610.                     }
  611.                 else {
  612.                     $ret $this->_copy_static_file($source_file$target_file);
  613.                 }
  614.             else {
  615.                 throw new TE_TMM_Exception("Source is not a file: ".$this->get_module_dir().'static/'.$source_file);
  616.             }
  617.         else {
  618.             throw new TE_TMM_Exception("Can't find source file: ".$this->get_module_dir().'static/'.$source_file);
  619.         }
  620.  
  621.         return $ret;
  622.     }
  623.  
  624.  
  625.     /**
  626.      * Actual copy of file
  627.      *
  628.      * @param string $source_file 
  629.      * @param string $target_file 
  630.      * @return boolean 
  631.      * @internal
  632.      * @throws TE_TMM_Exception
  633.      */
  634.     private function _copy_static_file($source_file$target_file{
  635.         $ret copy($this->get_module_dir().'static/'.$source_file$this->get_target_dir().$target_file);
  636.         if ($ret{
  637.             $this->add_to_files_list_file($this->get_target_dir().$target_file);
  638.         else {
  639.             throw new TE_TMM_Exception("Can't copy $source_file to ".$this->get_target_dir().$target_file);
  640.         }
  641.  
  642.         return $ret;
  643.     }
  644.  
  645.  
  646.     /**
  647.      * Creates module's config dir, i.e. where module.ctrl file will be installed
  648.      *
  649.      * @param string $modules_conf_dir 
  650.      */
  651.     protected function create_module_dir($modules_conf_dir{
  652.         $dir tangra_normalize_path($modules_conf_dir).$this->get_module_name().'/';
  653.         $this->create_dir($dir);
  654.     }
  655.  
  656.  
  657.     /**
  658.      * Creates directory and adds it to files list.
  659.      *
  660.      * If directory already exists is just added to files list.
  661.      *
  662.      * @param string $dir Directory to be created. Relative to target_path
  663.      * @throws TE_TMM_Exception
  664.      */
  665.     protected function create_dir($dir{
  666.         $dir $this->get_target_dir().$dir;
  667.         if (mkdir_ine($dir)) {
  668.             $this->add_to_files_list_dir($dir);
  669.         else {
  670.             throw new TE_TMM_Exception('Can not create dir: '.$dir);
  671.         }
  672.     }
  673.  
  674.  
  675.     /**
  676.      * Creates directory and adds it to files list.
  677.      *
  678.      * If directory already exists is just added to files list.
  679.      *
  680.      * @param string $dir Directory to be created specified with full path
  681.      */
  682.     protected function create_dir_full_path($dir{
  683.         if (mkdir_ine($dir)) {
  684.             $this->add_to_files_list_dir($dir);
  685.         else {
  686.             throw new TE_TMM_Exception('Can not create dir: '.$dir);
  687.         }
  688.     }
  689.  
  690.  
  691.     /**
  692.      * Compiles template file and writes the rezult in destination file. Adds full destination path to files list.
  693.      *
  694.      * @param Tangra_Simple_Tple $tple Template engine object with preassigned values that will be substituted
  695.      * @param string $file Temlate file
  696.      * @param string $destination_file Destination file
  697.      * @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.
  698.      * @throws TE_TMM_Item_Already_Exist
  699.      */
  700.     protected function compile_tpl_file(Tangra_Simple_Tple $tple$file$destination_file$special_file false{
  701.         $ret false;
  702.  
  703.         if (file_exists($this->get_target_dir().$destination_file)) {
  704.             if (!$special_file{
  705.                 if ($this->get_overwrite()) {
  706.                     $ret $this->_compile_tpl_file($tple$file$destination_file);
  707.                 else {
  708.                     throw new TE_TMM_Item_Already_Exist("Target file ".$this->get_target_dir().$destination_file." exists. Consider using overwrite parameter.");
  709.                 }
  710.             else {
  711.                 if ($this->get_overwrite_all()) {
  712.                     $ret $this->_compile_tpl_file($tple$file$destination_file);
  713.                 else {
  714.                     $ret $this->add_to_files_list_file($this->get_target_dir().$destination_file);
  715.                 }
  716.             }
  717.         else {
  718.             $ret $this->_compile_tpl_file($tple$file$destination_file);
  719.         }
  720.  
  721.         return $ret;
  722.     }
  723.  
  724.  
  725.     /**
  726.      * Actual compilation of template file
  727.      *
  728.      * @see compile_tpl_file()
  729.      *
  730.      * @param Tangra_Simple_Tple $tple 
  731.      * @param string $file 
  732.      * @param string $destination_file 
  733.      * @internal
  734.      * @throws TE_TMM_Exception
  735.      */
  736.     private function _compile_tpl_file(Tangra_Simple_Tple $tple$file$destination_file{
  737.         $ret false;
  738.  
  739.         $content $tple->fetch($file);
  740.  
  741.         if (file_put_contents($this->get_target_dir().$destination_file$content)) {
  742.             $this->add_to_files_list_file($this->get_target_dir().$destination_file);
  743.             $ret true;
  744.         else {
  745.             throw new TE_TMM_Exception('Failed to create compiled file: '.$this->get_target_dir().$destination_file);
  746.         }
  747.  
  748.         return $ret;
  749.     }
  750.  
  751.  
  752.     /**
  753.      * Creates symlink and adds it to files list
  754.      *
  755.      * @param string $source_file Source file that symlink will point to
  756.      * @param string $link_name Link name
  757.      * @param string $alternative_source_for_copy If symlinks are not available (like in Windows), just copy this file instead of creating symlink
  758.      * @throws TE_TMM_Exception,TE_TMM_Item_Already_Exist
  759.      */
  760.     protected function create_sym_link($source_file$link_name$alternative_source_for_copy ''{
  761.         if (function_exists('symlink'&& !is_windows()) {
  762.             if (file_exists($this->get_target_dir().$link_name)) {
  763.                 if ($this->get_overwrite()) {
  764.                     if (!is_dir($this->get_target_dir().$link_name)) {
  765.                         unlink($this->get_target_dir().$link_name);
  766.                         $ret $this->_create_sym_link($source_file$link_name);
  767.                     else {
  768.                         throw new TE_TMM_Exception('Unable to create symlink because dir with same name exists: '.$this->get_target_dir().$link_name);
  769.                     }
  770.                 else {
  771.                     throw new TE_TMM_Item_Already_Exist("File/directory ".$this->get_target_dir().$link_name." already exists. Consider using option 'overwrite'.");
  772.                 }
  773.             else {
  774.                 $ret $this->_create_sym_link($source_file$link_name);
  775.             }
  776.         else {
  777.             if ($alternative_source_for_copy{
  778.                 $ret $this->copy_static_file($alternative_source_for_copy$link_name);
  779.             else {
  780.                 $ret copy($this->get_target_dir().$source_file$this->get_target_dir().$link_name);
  781.                 $this->add_to_files_list_file($this->get_target_dir().$source_file);
  782.             }
  783.         }
  784.  
  785.         if (!$ret{
  786.             throw new TE_TMM_Exception('Failed to create file: '.$this->get_target_dir().$link_name);
  787.         }
  788.     }
  789.  
  790.  
  791.     /**
  792.      * Enter description here...
  793.      *
  794.      * @param string $source_file 
  795.      * @param string $link_name 
  796.      * @return boolean 
  797.      * @throws TE_TMM_Exception
  798.      */
  799.     private function _create_sym_link($source_file$link_name{
  800.         $ret @symlink($this->get_target_dir().$source_file$this->get_target_dir().$link_name);
  801.         $this->add_to_files_list_symlink($this->get_target_dir().$link_name);
  802.  
  803.         if (!$ret{
  804.             throw new TE_TMM_Exception('Failed to create symlink: '.$this->get_target_dir().$link_name);
  805.         }
  806.  
  807.         return $ret;
  808.     }
  809.  
  810.  
  811.     /**
  812.      * Copies module.ctrl file to modules conf dir
  813.      *
  814.      * @internal
  815.      * @throws TE_TMM_Exception
  816.      */
  817.     private function copy_module_ctrl({
  818.         if (file_exists($this->get_module_dir().'module.ctrl.xml')) {
  819.             $ret copy($this->get_module_dir().'module.ctrl.xml'$this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/module.ctrl.xml');
  820.             if (!$ret{
  821.                 throw new TE_TMM_Exception('Failed to copy file: '.$this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/module.ctrl');
  822.             }
  823.  
  824.             $this->add_to_files_list_file($this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/module.ctrl.xml');
  825.         else {
  826.             $ret copy($this->get_module_dir().'module.ctrl'$this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/module.ctrl');
  827.             if (!$ret{
  828.                 throw new TE_TMM_Exception('Failed to copy file: '.$this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/module.ctrl');
  829.             }
  830.  
  831.             $this->add_to_files_list_file($this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/module.ctrl');
  832.         }
  833.  
  834.     }
  835.  
  836.  
  837.     /**
  838.      * Adds new section to conf file
  839.      *
  840.      * @param string $file Path to config file relative to site target dir
  841.      * @param string $section_content Content of the section
  842.      * @param boolean $strict If true will throw exception if section already exists.
  843.      * @throws TE_TMM_Exception
  844.      */
  845.     protected function add_section_to_conf_file($file$section_content$strict false{
  846.         $full_path $this->get_target_dir().$file;
  847.  
  848.         if (file_exists($full_path)) {
  849.             $arr file($full_path);
  850.  
  851.             $boundaries $this->find_start_and_end_of_conf_section($arr);
  852.  
  853.             if (!$boundaries{
  854.                 $this->_add_section_to_conf_file($full_path$section_content);
  855.             else {
  856.                 if ($this->get_overwrite_all()) {
  857.                     $this->remove_section_from_conf_file($file);
  858.                     $this->_add_section_to_conf_file($full_path$section_content);
  859.                 else {
  860.                     if ($strict{
  861.                         throw new TE_TMM_Exception('Configuration section for module "'.$this->get_module_name().'" already exist starting at: '.$boundaries['start']);
  862.                     }
  863.                 }
  864.             }
  865.         else {
  866.             throw new TE_TMM_Exception('Configuration file does not exists: '.$this->get_target_dir().$file);
  867.         }
  868.     }
  869.  
  870.  
  871.     /**
  872.      * Actual adding of section to conf file
  873.      *
  874.      * @param string $full_path Full path to conf file
  875.      * @param string $section_content Content of the section
  876.      * @internal
  877.      */
  878.     private function _add_section_to_conf_file($full_path$section_content{
  879.  
  880.         file_put_contents($full_path$start_tagFILE_APPEND);
  881.         file_put_contents($full_path$section_contentFILE_APPEND);
  882.         file_put_contents($full_path$end_tagFILE_APPEND);
  883.     }
  884.  
  885.  
  886.     /**
  887.      * Removes module section from conf file
  888.      *
  889.      * @param string $file Path to conh file relative to site target dir
  890.      * @param boolean $strict If true will throw exception if section does not exists.
  891.      * @throws TE_TMM_Exception
  892.      */
  893.     protected function remove_section_from_conf_file($file$strict true{
  894.         $full_path $this->get_target_dir().$file;
  895.  
  896.         if (file_exists($this->get_target_dir().$file)) {
  897.             $arr file($this->get_target_dir().$file);
  898.  
  899.             $boundaries $this->find_start_and_end_of_conf_section($arr);
  900.             if ($boundaries{
  901.                 for ($i $boundaries['start']$i <= $boundaries['end']$i++{
  902.                     unset($arr[$i]);
  903.                 }
  904.  
  905.                 $file_content implode(''$arr);
  906.                 file_put_contents($full_path$file_content);
  907.             else {
  908.                 throw new TE_TMM_Exception('Configuration section for module "'.$this->get_module_name().'" does not exist.');
  909.             }
  910.         else {
  911.             throw new TE_TMM_Exception('Configuration file does not exists: '.$this->get_target_dir().$file);
  912.         }
  913.     }
  914.  
  915.  
  916.     /**
  917.      * Find start and end indexes of module's section
  918.      *
  919.      * @param array $arr 
  920.      * @return array Structured array  'start' => start index, 'end' => end index
  921.      * @internal
  922.      */
  923.     private function find_start_and_end_of_conf_section($arr{
  924.         $ret false;
  925.  
  926.  
  927.         $start_found false;
  928.         $end_found false;
  929.  
  930.         for ($i 0$i count($arr)$i++{
  931.             if (strpos($arr[$i]trim($start_tag)) !== false{
  932.                 $start_found $i;
  933.                 break;
  934.             }
  935.         }
  936.  
  937.         if ($start_found !== false{
  938.             for ($i $start_found$i count($arr)$i++{
  939.                 if (strpos($arr[$i]trim($end_tag)) !== false{
  940.                     $end_found $i;
  941.                     break;
  942.                 }
  943.             }
  944.         }
  945.  
  946.         if ($start_found !== false && $end_found !== false{
  947.             $ret['start'$start_found;
  948.             $ret['end'$end_found;
  949.         }
  950.  
  951.  
  952.         return $ret;
  953.     }
  954.  
  955. //
  956. //    /**
  957. //     * Changes file permisssions and groups
  958. //     *
  959. //     * @see set_file_permissions(), set_file_group()
  960. //     * @internal
  961. //     *
  962. //     */
  963. //    private function change_file_properties() {
  964. //        $file_perm = $this->get_file_permissions();
  965. //        $dir_perm = $this->get_dir_permissions();
  966. //        $file_group = $this->get_file_group();
  967. //
  968. //        if ($file_group || $file_perm || $dir_perm) {
  969. //            foreach($this->files as $item) {
  970. //                if (is_file($item['item']) || is_link($item['item'])) {
  971. //                    if ($file_perm) {
  972. //                        $rez = @chmod($item['item'], octdec('0'.$file_perm));
  973. //                    }
  974. //                }
  975. //
  976. //                if (is_dir($item['item'])) {
  977. //                    if ($dir_perm) {
  978. //                        $rez = @chmod($item['item'], octdec('0'.$dir_perm));
  979. //                    }
  980. //                }
  981. //
  982. //                if ($file_group) {
  983. //                    $rez = @chgrp($item['item'], $file_group);
  984. //                }
  985. //            }
  986. //        }
  987. //    }
  988.  
  989.  
  990.     /**
  991.      * Deinstallation of the module
  992.      *
  993.      * Incomplete method. TCC has functionality to remove modules.
  994.      *
  995.      */
  996.     public function uninstall($params{
  997.         //TODO
  998.     }
  999.  
  1000.  
  1001.     /**
  1002.      * Adds file to files list
  1003.      *
  1004.      * @param string $item Full path to the file
  1005.      */
  1006.     protected function add_to_files_list_file($item{
  1007.         $this->set_item_permissions($item);
  1008.  
  1009.         $item_abs $this->abstract_path($item);
  1010.  
  1011.         array_push($this->filesarray('item' => $item_abs,
  1012.                                         'type' => TMM_INSTALL_ITEM_TYPE_FILE,
  1013.                                         'checksum' => md5_file($item)));
  1014.  
  1015.     }
  1016.  
  1017.  
  1018.     /**
  1019.      * Adds dir to files list
  1020.      *
  1021.      * @param string $item Full path to the dir
  1022.      */
  1023.     protected function add_to_files_list_dir($item{
  1024.         $this->set_item_permissions($item);
  1025.         $item $this->abstract_path($item);
  1026.  
  1027.         array_push($this->filesarray('item' => tangra_normalize_path($item),
  1028.                                         'type' => TMM_INSTALL_ITEM_TYPE_DIR));
  1029.  
  1030.     }
  1031.  
  1032.  
  1033.     /**
  1034.      * Adds symlink to files list
  1035.      *
  1036.      * @param string $item Full path to the symlink
  1037.      */
  1038.     protected function add_to_files_list_symlink($item{
  1039.         $item $this->abstract_path($item);
  1040.  
  1041.         array_push($this->filesarray('item' => $item,
  1042.                                         'type' => TMM_INSTALL_ITEM_TYPE_SYMLINK));
  1043.     }
  1044.  
  1045.  
  1046.     /**
  1047.      * Converts full path to abstract path, this way files.list is portable between depoyments
  1048.      *
  1049.      * 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
  1050.      *
  1051.      * @param string $item Full path of a item
  1052.      * @return string abstracted path
  1053.      */
  1054.     private function abstract_path($item{
  1055.         $target_dir $this->get_target_dir();
  1056.  
  1057.         $item str_replace($target_dir.'hidden/''%HIDDEN%'$item);
  1058.         $item str_replace($target_dir.'htdocs/''%HTDOCS%'$item);
  1059.         $item str_replace($target_dir.'ext_inc/''%EXT_INC%'$item);
  1060.         $item str_replace($target_dir.'scratch/''%SCRATCH%'$item);
  1061.  
  1062.         return $item;
  1063.     }
  1064.  
  1065.  
  1066.  
  1067.     /**
  1068.      * Compiles bulk of files contained in $source_dir into $destination_dir
  1069.      *
  1070.      * @param Tangra_Simple_Tple $tple Tangra_Simple_Tple instance. You have to set all exports before calling this method
  1071.      * @param string $source_dir Relative to $tple->get_tpl_path(). Example: 'htdocs'
  1072.      * @param string $destination_dir Relative to  $this->get_target_dir(). Example: 'htdocs/admin'
  1073.      * @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.
  1074.      */
  1075.     protected function compile_bulk(Tangra_Simple_Tple $tple$source_dir$destination_dir$is_root true{
  1076.         $destination_dir tangra_normalize_path($this->get_target_dir().$destination_dir);
  1077.         $source_dir $tple->get_tpl_path().$source_dir;
  1078.  
  1079.         $this->_compile_bulk($tple$source_dir$destination_dir$is_root);
  1080.     }
  1081.  
  1082.  
  1083.     /**
  1084.      * Actual compilation of bulk files. See compile_bulk();
  1085.      *
  1086.      * This method is not ment to be called directly by the user. Use compile_bulk() instead.
  1087.      *
  1088.      * @param Tangra_Simple_Tple $tple Tangra_Simple_Tple instance. You have to set all exports before calling this method
  1089.      * @param string $source_dir Relative to $tple->get_tpl_path(). Example: 'htdocs'
  1090.      * @param string $destination_dir Relative to  $this->get_target_dir(). Example: 'htdocs/admin'
  1091.      * @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.
  1092.      * @throws TE_TMM_Item_Already_Exist,TE_TMM_Exception
  1093.      */
  1094.     private function _compile_bulk(Tangra_Simple_Tple $tple$source_dir$destination_dir$is_root true{
  1095.         if (!$is_root{
  1096.             if (mkdir_ine($destination_dir)) {
  1097.                 $this->add_to_files_list_dir($destination_dir);
  1098.             else {
  1099.                 throw new TE_TMM_Exception("Can't create dir $destination_dir/$item");
  1100.             }
  1101.         }
  1102.  
  1103.         if ($dir opendir($source_dir)) {
  1104.             while (($item readdir($dir)) !== false{
  1105.                 if ($item != '.' && $item != '..'{
  1106.                     if (file_exists("$destination_dir$item"&& !is_dir("$destination_dir$item")) {
  1107.                         if (!$this->get_overwrite()) {
  1108.                             throw new TE_TMM_Item_Already_Exist("File "."$destination_dir$item already exists. Consider using option 'overwrite'.");
  1109.                         }
  1110.                     }
  1111.  
  1112.                     if (is_file("$source_dir/$item")) {
  1113.                         if ($this->compile_tpl_file($tplestr_replace($tple->get_tpl_path()''"$source_dir/$item")str_replace($this->get_target_dir()''"$destination_dir$item")false)) {
  1114.                             $this->add_to_files_list_file("$destination_dir$item");
  1115.                         else {
  1116.                             throw new TE_TMM_Exception("Can't compile $source_dir/$item to $destination_dir$item");
  1117.                         }
  1118.                     else {
  1119.                         if ($item != '.svn'{
  1120.                             $tmp_arr $this->_compile_bulk($tple"$source_dir/$item"tangra_normalize_path($destination_dir).$item.'/'false);
  1121.                         else {
  1122.                             continue;
  1123.                         }
  1124.                     }
  1125.                 }
  1126.             }
  1127.             closedir($dir);
  1128.         }
  1129.     }
  1130.  
  1131.  
  1132.     /**
  1133.      * This function is called to check if installer can upgrade from given version.
  1134.      *
  1135.      * @param string $from_version 
  1136.      * @return boolean 
  1137.      */
  1138.     public function can_upgrade($from_version{
  1139.         $ret $this->get_upgrade_method($from_version$from_version false;
  1140.  
  1141.         return $ret;
  1142.     }
  1143.  
  1144.  
  1145.     /**
  1146.      * Activities that have to be performed before actual upgrade have to be placed here.
  1147.      *
  1148.      * If you overwrite this method don't forget to call parent::pre_upgrade()
  1149.      *
  1150.      * @param string $from_version 
  1151.      */
  1152.     public function pre_upgrade($from_version{
  1153.         $this->backup_files_list($from_version);
  1154.     }
  1155.  
  1156.  
  1157.     /**
  1158.      * Makes a copy of current files.list in order to be used later when generating new one (after upgrade)
  1159.      *
  1160.      * @param string $from_version 
  1161.      */
  1162.     protected function backup_files_list($from_version{
  1163.         $module_conf_dir $this->get_target_dir().'hidden/conf/modules/'.$this->get_module_name().'/';
  1164.         $files_list_path $module_conf_dir.'files.list';
  1165.         $files_list_old $module_conf_dir.'files.list.'.$from_version;
  1166.         $rez @copy($files_list_path$files_list_old);
  1167.         if (!$rez{
  1168.             throw new TE_TMM_Exception('Cannot copy '.$files_list_path.' to '.$files_list_old);
  1169.         }
  1170.     }
  1171.  
  1172.  
  1173.  
  1174.  
  1175.     /**
  1176.      * Performs upgrade of module
  1177.      *
  1178.      * @param string $from_version 
  1179.      */
  1180.     public function upgrade($from_version{
  1181.         $method_name $this->get_upgrade_method($from_version);
  1182.         if ($method_name{
  1183.             $this->$method_name($from_version);
  1184.         }
  1185.     }
  1186.  
  1187.  
  1188.     /**
  1189.      * Activities that have to be performed after actual upgrade have to be placed here.
  1190.      *
  1191.      * If you overwrite this method don't forget to call parent::post_upgrade()
  1192.      *
  1193.      * @param string $from_version 
  1194.      */
  1195.     public function post_upgrade($from_version{
  1196.  
  1197.     }
  1198.  
  1199.  
  1200.     /**
  1201.      * Adds new class method that will handle upgrade from particular version
  1202.      *
  1203.      * @param string $version 
  1204.      * @param string $method_name 
  1205.      */
  1206.     protected function set_upgrade_method($version$method_name{
  1207.         if (is_callable(array($this$method_name))) {
  1208.             $this->upgrade_matrix[$version$method_name;
  1209.         else {
  1210.             throw new TE_TMM_Exception("Method $method_name does not exist");
  1211.         }
  1212.     }
  1213.  
  1214.  
  1215.     /**
  1216.      * Returns name of the method that will perform upgrade from version $from_version
  1217.      *
  1218.      * Name of the metod is lookup in $this->upgrade_matrix
  1219.      *
  1220.      * @param string $from_version 
  1221.      */
  1222.     protected function get_upgrade_method($from_version{
  1223.         $ret false;
  1224.  
  1225.         if (array_key_exists($from_version$this->upgrade_matrix)) {
  1226.             $ret $this->upgrade_matrix[$from_version];
  1227.         }
  1228.  
  1229.         return $ret;
  1230.     }
  1231.  
  1232.  
  1233.     public function init_can_upgrade({
  1234.         $can_upgrade_loader new Can_Upgrade_Loader($this->get_module_dir().'can_upgrade');
  1235.         $arr $can_upgrade_loader->get_can_upgrade();
  1236.         foreach($arr as $version => $method{
  1237.             $this->set_upgrade_method($version$method);
  1238.         }
  1239.     }
  1240.     
  1241.     
  1242.     public function set_error_reporting_php4_lib({
  1243.         global $ERROR_REPORTING_PHP4_LIBS;
  1244.  
  1245.         error_reporting($ERROR_REPORTING_PHP4_LIBS);
  1246.     }
  1247.     
  1248.     
  1249.     public function set_error_reporting_normal({
  1250.         global $ERROR_REPORTING;
  1251.  
  1252.         error_reporting($ERROR_REPORTING);        
  1253.     }
  1254. }