[ Index ]

PHP Cross Reference of Akelos Framework

title

Body

[close]

/ -> AkPluginInstaller.php (source)

   1  <?php
   2  require_once (AK_LIB_DIR.DS.DS.'AkType.php');
   3  require_once (AK_LIB_DIR.DS.'AkInstaller.php');
   4  require_once (AK_LIB_DIR.DS.'AkReflection'.DS.'AkReflectionFile.php');
   5  
   6  
   7  defined('AK_PLUGINS_DIR') ? null : define('AK_PLUGINS_DIR', AK_APP_DIR.DS.'vendors'.DS.'plugins');
   8  
   9  class AkPluginInstaller extends AkInstaller
  10  {
  11      var $auto_install_files = true;
  12      var $auto_install_extensions = true;
  13      var $auto_remove_extensions = true;
  14      
  15      var $plugin_name;
  16      
  17      var $extension_points = array('BaseActiveRecord'=>'base_active_record.php',
  18                                    'BaseActionController'=>'base_action_controller.php');
  19  
  20      var $_plugin_definition;
  21      
  22      function AkPluginInstaller($db_connection = null, $plugin_name = '')
  23      {
  24          $this->AkInstaller($db_connection);
  25          $this->plugin_name = $plugin_name;
  26      }
  27      function _runInstallerMethod($method_prefix, $version, $options = array(), $version_number = null)
  28      {
  29          $auto_install_extensions = (isset($this->auto_install_extensions) && $this->auto_install_extensions === true);
  30          $auto_install_files = (isset($this->auto_install_files) && $this->auto_install_files === true);
  31          
  32          $auto_remove_extensions = (isset($this->auto_remove_extensions) && $this->auto_remove_extensions === true);
  33          
  34          
  35          $method_name = $method_prefix.'_'.$version;
  36          $method_exists = method_exists($this, $method_name);
  37          
  38          if(!$method_exists){
  39              return false;
  40          }
  41  
  42          $version_number = empty($version_number) ? ($method_prefix=='down' ? $version-1 : $version) : $version_number;
  43  
  44          $this->transactionStart();
  45          switch ($method_prefix) {
  46              case 'up':
  47                  $depdencies_ok = $this->_checkInstallDependencies();
  48                  
  49                  break;
  50              case 'down':
  51              case 'uninstall':
  52                  $depdencies_ok = $this->_checkUninstallDependencies();
  53                  break;
  54              default:
  55                  $depdencies_ok = true;
  56          }
  57          
  58          if ($depdencies_ok === false) {
  59              $this->transactionFail();
  60              return $depdencies_ok;
  61          }
  62          if ($method_prefix == 'up') {
  63              if ($auto_install_files) {
  64                  $res = $this->installFiles();
  65                  if ($res === false) {
  66                      $this->transactionFail();
  67                      return $res;
  68                  }
  69              }
  70              if ($auto_install_extensions) {
  71                  $res = $this->autoInstallExtensions();
  72                  if ($res === false) {
  73                      $this->transactionFail();
  74                      return $res;
  75                  }
  76              }
  77          }
  78          if ($method_prefix == 'down' || $method_prefix == 'uninstall') {
  79              if ($auto_remove_extensions) {
  80                  $this->removeExtensions();
  81              }
  82              $this->_removeDependency();
  83          }
  84          if($this->$method_name($options) === false){
  85              $this->transactionFail();
  86          }
  87          $success = !$this->transactionHasFailed();
  88          $this->transactionComplete();
  89          if($success){
  90              $this->setInstalledVersion($version_number, $options);
  91          }
  92          return $success;
  93      }
  94      
  95  
  96      function installFiles($installer_dir = 'installer', $source_dir = 'files')
  97      {
  98          $basePath = AK_APP_PLUGINS_DIR.DS.$this->plugin_name.DS.$installer_dir.DS.$source_dir;
  99          $this->files = Ak::dir($basePath, array('recurse'=> true));
 100          empty($this->options['force']) ? $this->_checkForCollisions($this->files,$basePath) : null;
 101          $this->_copyFiles($this->files, $basePath, $basePath);
 102      }
 103      
 104      function _copyFiles($directory_structure, $base_path = null, $src_path = null)
 105      {
 106          
 107          foreach ($directory_structure as $k=>$node){
 108              $path = $base_path.DS.$node;
 109              if(is_dir($path)){
 110                  echo 'Creating dir '.$path."\n";
 111                  $this->_makeDir($path, $src_path);
 112              }elseif(is_file($path)){
 113                  echo 'Creating file '.$path."\n";
 114                  $this->_copyFile($path, $src_path);
 115              }elseif(is_array($node)){
 116                  foreach ($node as $dir=>$items){
 117                      $path = $base_path.DS.$dir;
 118                      if(is_dir($path)){
 119                          echo 'Creating dir '.$path."\n";
 120                          $this->_makeDir($path, $src_path);
 121                          $this->_copyFiles($items, $path, $src_path);
 122                      }
 123                  }
 124              }
 125          }
 126      }
 127  
 128      function _makeDir($path, $base_path)
 129      {
 130          $dir = str_replace($base_path, AK_BASE_DIR,$path);
 131          if(!is_dir($dir)){
 132              mkdir($dir);
 133          }
 134      }
 135      function _removeDependency()
 136      {
 137          if (!empty($this->dependencies)) {
 138              $this->dependencies = Ak::toArray($this->dependencies);
 139              
 140              foreach ($this->dependencies as $dependency) {
 141                  $dependencyFile = AK_PLUGINS_DIR.DS.$dependency.DS.'dependent_plugins';
 142                  if (($fileExists = file_exists($dependencyFile))) {
 143                      $dependendPlugins = file($dependencyFile);
 144                  } else {
 145                      $dependendPlugins = array();
 146                  }
 147                  $dependendPlugins = array_diff($dependendPlugins,array($this->plugin_name));
 148                  if (!empty($dependendPlugins)) {
 149                      Ak::file_put_contents($dependencyFile,implode("\n",$dependendPlugins));
 150                  } else if ($fileExists) {
 151                      unlink($dependencyFile);
 152                  }
 153              }
 154          }
 155      }
 156      function _copyFile($path, $base_path)
 157      {
 158          $destination_file = str_replace($base_path, AK_BASE_DIR,$path);
 159          copy($path, $destination_file);
 160          $source_file_mode =  fileperms($path);
 161          $target_file_mode =  fileperms($destination_file);
 162          if($source_file_mode != $target_file_mode){
 163              chmod($destination_file,$source_file_mode);
 164          }
 165      }
 166      
 167      function _checkForCollisions(&$directory_structure, $base_path = null)
 168      {
 169          foreach ($directory_structure as $k=>$node){
 170              if(!empty($this->skip_all)){
 171                  return ;
 172              }
 173              $path = str_replace($base_path, AK_BASE_DIR, $base_path.DS.$node);
 174              if(is_file($path)){
 175                  $message = Ak::t('File %file exists.', array('%file'=>$path));
 176                  $user_response = AkInstaller::promptUserVar($message."\n d (overwrite mine), i (keep mine), a (abort), O (overwrite all), K (keep all)", 'i');
 177                  if($user_response == 'i'){
 178                      unset($directory_structure[$k]);
 179                  }    elseif($user_response == 'O'){
 180                      return false;
 181                  }    elseif($user_response == 'K'){
 182                      $directory_structure = array();
 183                      return false;
 184                  }elseif($user_response != 'd'){
 185                      echo "\nAborting\n";
 186                      exit;
 187                  }
 188              }elseif(is_array($node)){
 189                  foreach ($node as $dir=>$items){
 190                      $path = $base_path.DS.$dir;
 191                      if(is_dir($path)){
 192                          if($this->_checkForCollisions($directory_structure[$k][$dir], $path) === false){
 193                              $this->skip_all = true;
 194                              return;
 195                          }
 196                      }
 197                  }
 198              }
 199          }
 200      }
 201      
 202  
 203      function _addMethodToClass($class,$name,$path,$methodString, $pluginName)
 204      {
 205          $targetReflection = new AkReflectionFile($path);
 206          $classes = $targetReflection->getClasses();
 207          foreach($classes as $c) {
 208              $method = $c->getMethod($name);
 209              if ($method!==false) {
 210                  echo "Method $name already exists on class $class in file $path\n";
 211                  return false;
 212              }
 213          }
 214          $contents = @Ak::file_get_contents($path);
 215         
 216              return (Ak::file_put_contents($path, preg_replace('|class '.$class.'(.*?)\n.*?{|i',"class $class\\1
 217  {
 218  /** AUTOMATED START: $pluginName::$name */
 219  $methodString
 220  /** AUTOMATED END: $pluginName::$name */
 221  ",$contents))>0?true:'Could not write to '.$path);
 222          
 223      }
 224      function _removeMethodFromClass($path,$name,$pluginName)
 225      {
 226          return Ak::file_put_contents($path, preg_replace("|(\n[^\n]*?/\*\* AUTOMATED START: $pluginName::$name \*/.*?/\*\* AUTOMATED END: $pluginName::$name \*/\n)|s","",Ak::file_get_contents($path)));
 227      }
 228      function autoInstallExtensions()
 229      {
 230          $path = AK_APP_PLUGINS_DIR.DS.$this->plugin_name.DS.'extensions';
 231          $extensionFiles = Ak::dir($path,array('recurse'=>true));
 232          foreach($extensionFiles as $extensionFile) {
 233              $this->installExtensions('extensions'.DS.$extensionFile);
 234          }
 235      }
 236      function installExtensions($fromFile,$pluginIdentifier = null)
 237      {
 238          if (substr($fromFile,0,5) == 'file:') {
 239              $fromFile = substr($fromFile,5);
 240          } else {
 241              $basePath = AK_APP_VENDOR_DIR.DS.'plugins'.DS.$this->plugin_name.DS;
 242              $fromFile = $basePath.DS.$fromFile;
 243          }
 244          if ($pluginIdentifier==null) {
 245              $pluginIdentifier = AkInflector::camelize($this->plugin_name);
 246          }
 247          $reflection = new AkReflectionFile($fromFile);
 248          unset($reflection->tokens);
 249          $classes = $reflection->getClasses();
 250          foreach ($classes as $class) {
 251              $install = $class->getTag('ExtensionPoint');
 252              if ($install!==false) {
 253                  $methods = $class->getMethods();
 254                  $installAll = true;
 255              } else {
 256                  $installAll = false;
 257                  $methods = $class->getMethods(array('tags'=>array('ExtensionPoint'=>'.*')));
 258              }
 259              foreach ($methods as $method) {
 260                  if ($installAll) {
 261                      $class = $install;
 262                      $methodAlias = $method->getName();
 263                  } else {
 264                      $installAs = $method->getTag('ExtensionPoint');
 265                      $parts=split('::',$installAs);
 266                      $class = $parts[0];
 267                      if (!isset($parts[1])) {
 268                          $methodAlias = $method->getName();
 269                      } else {
 270                          $methodAlias = $parts[1];
 271                      }
 272                  }
 273                  $class = trim($class);
 274                  $methodAlias = trim($methodAlias);
 275                  $method->setTag('Plugin',$pluginIdentifier);
 276                  if (isset($this->extension_points[$class])) {
 277                      $path = AK_APP_DIR.DS.$this->extension_points[$class];
 278                      $this->_addMethodToClass($class,$methodAlias,$path,$method->toString(4,$methodAlias),$pluginIdentifier);
 279                  }
 280              }
 281          }
 282      }
 283      function _checkUninstallDependencies()
 284      {
 285          $dependencyFile = AK_PLUGINS_DIR.DS.$this->plugin_name.DS.'dependent_plugins';
 286          
 287          if (file_exists($dependencyFile)) {
 288              $dependendPlugins = file($dependencyFile);
 289              if (!empty($dependendPlugins)) {
 290                  if (empty($this->options['force'])) {
 291                      echo "\n";
 292                      echo Ak::t("The following %plugin %dependent depend on the plugin you are about to uninstall.",array('%plugin'=>AkT('plugin','quantify('.count($dependendPlugins).')'),'%dependent'=>AkT($dependendPlugins,'toSentence')));
 293                      echo Ak::t("Please uninstall the dependent %plugin first.",array('%plugin'=>AkT('plugin','quantify('.count($dependendPlugins).')')));
 294                      echo "\n";
 295                      $this->transactionFail();
 296                      die();
 297                  } else {
 298                      echo "\n";
 299                      echo Ak::t("The following %plugin %dependent depend on the plugin you are about to uninstall.",array('%plugin'=>AkT('plugin','quantify('.count($dependendPlugins).')'),'%dependent'=>AkT($dependendPlugins,'toSentence')));
 300                      echo "\n";
 301                      $uninstall = AkInstaller::promptUserVar(
 302          'Are you sure you want to continue uninstalling (Answer with Yes)? The other plugins will malfunction.', array('default'=>'N'));
 303                      if ($uninstall != 'Yes') {
 304                          echo Ak::t('Uninstall cancelled.');
 305                          echo "\n";
 306                          $this->transactionFail();
 307                          die();
 308                      } else {
 309                          return true;
 310                      }
 311                  }
 312              }
 313              return true;
 314          }
 315  
 316      }
 317      function _checkInstallDependencies()
 318      {
 319          if (isset($this->php_min_version)) {
 320              if(version_compare(PHP_VERSION,$this->php_min_version,'<')) {
 321                  trigger_error(Ak::t("This plugin requires at least php version: %version", array('%version'=>$this->php_min_version)), E_USER_ERROR);
 322              }
 323          }
 324  
 325          if (isset($this->php_max_version)) {
 326              if(version_compare(PHP_VERSION,$this->php_max_version,'>')) {
 327                  trigger_error("This plugin runs only on php version <= %version", array('%version'=>$this->php_min_version), E_USER_ERROR);
 328              }
 329          }
 330          if (isset($this->dependencies)) {
 331              $this->dependencies = Ak::toArray($this->dependencies);
 332              $pluginManager = new AkPluginManager();
 333              $plugins = $pluginManager->getInstalledPlugins();
 334              $missing = array();
 335              foreach ($this->dependencies as $dependency) {
 336                  if (!in_array($dependency,$plugins)) {
 337                      $missing[] = $dependency;
 338                  }
 339              }
 340              if (!empty($missing)) {
 341                  echo "\n";
 342                  $params = array('plugin'=>AkT('plugin','quantify('.count($missing).')'),'missing'=>AkT($missing,'toSentence'));
 343                  echo Ak::t("This plugin depends on the %plugin %missing. Please install the missing plugins first.",$params);
 344                  echo "\n";
 345                  return false;
 346              } else {
 347                  /**
 348                   * register the dependent plugins
 349                   */
 350                  foreach ($this->dependencies as $dependency) {
 351                      $dependencyFile = AK_PLUGINS_DIR.DS.$dependency.DS.'dependent_plugins';
 352                      if (($fileExists = file_exists($dependencyFile))) {
 353                          $dependendPlugins = file($dependencyFile);
 354                      } else {
 355                          $dependendPlugins = array();
 356                      }
 357                      if (!in_array($this->plugin_name,$dependendPlugins)) {
 358                          $dependendPlugins[] = $this->plugin_name;
 359                          
 360                      }
 361                      if (!empty($dependendPlugins)) {
 362                          Ak::file_put_contents($dependencyFile,implode("\n",$dependendPlugins));
 363                      } else if ($fileExists) {
 364                          unlink($dependencyFile);
 365                      }
 366                      
 367                  }
 368              }
 369          }
 370          return true;
 371      }
 372      function removeExtensions($pluginIdentifier = null)
 373      {
 374          
 375          if ($pluginIdentifier == null) {
 376              $pluginIdentifier = AkInflector::camelize($this->plugin_name);
 377          }
 378  
 379          foreach ($this->extension_points as $targetClass=>$baseFile) {
 380              $file = AK_APP_DIR.DS.$baseFile;
 381              $reflection = new AkReflectionFile($file);
 382              $classes = $reflection->getClasses();
 383              foreach ($classes as $class) {
 384                  $methods = $class->getMethods(array('tags'=>array('Plugin'=>$pluginIdentifier)));
 385                  foreach ($methods as $method) {
 386                      $this->_removeMethodFromClass($file,$method->getName(),$pluginIdentifier);
 387                  }
 388              }
 389          }
 390      }
 391  
 392  }
 393  ?>


Generated: Mon Oct 27 12:43:49 2008 Cross-referenced by PHPXref 0.6