| [ Index ] |
PHP Cross Reference of Akelos Framework |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Oct 27 12:43:49 2008 | Cross-referenced by PHPXref 0.6 |