00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 class installerException extends Exception {
00046 public $extension = null;
00047
00048 public function __construct ($message, $extension) {
00049 $basemessage = T_('Installer error: XML file %s for extension %s - ');
00050 $this->extension = $extension;
00051 parent::__construct($basemessage.$message, 0);
00052 }
00053
00054 }
00055
00056 class aliroLanguageHandler extends aliroCommonExtHandler {
00057 protected static $instance = __CLASS__;
00058 protected $extensiondir = '/language/';
00059
00060
00061 public static function getInstance () {
00062 return is_object(self::$instance) ? self::$instance : (self::$instance = parent::getCachedSingleton(self::$instance));
00063 }
00064 }
00065
00066 class aliroPatchHandler extends aliroCommonExtHandler {
00067 protected static $instance = __CLASS__;
00068 protected $extensiondir = '/';
00069
00070
00071 public static function getInstance () {
00072 return is_object(self::$instance) ? self::$instance : (self::$instance = parent::getCachedSingleton(self::$instance));
00073 }
00074 }
00075
00076 class aliroIncludeHandler extends aliroCommonExtHandler {
00077 protected static $instance = __CLASS__;
00078 protected $extensiondir = '/includes/';
00079
00080
00081 public static function getInstance () {
00082 return is_object(self::$instance) ? self::$instance : (self::$instance = parent::getCachedSingleton(self::$instance));
00083 }
00084 }
00085
00086 class aliroParameterHandler extends aliroCommonExtHandler {
00087 protected static $instance = __CLASS__;
00088 protected $extensiondir = '/parameters/';
00089
00090
00091 public static function getInstance () {
00092 return is_object(self::$instance) ? self::$instance : (self::$instance = parent::getCachedSingleton(self::$instance));
00093 }
00094 }
00095
00096 class aliroExtensionInstaller extends aliroFriendlyBase {
00097
00098
00099
00100 protected $xmlfile = '';
00101 protected $xmlobject = null;
00102 protected $here = '';
00103 protected $purifier = null;
00104
00105
00106 protected $handler = null;
00107
00108 public function __construct ($xmlfile) {
00109 $this->xmlfile = $xmlfile;
00110 $this->xmlobject = new aliroXML;
00111 try {
00112 $this->xmlobject->loadFile($xmlfile);
00113 } catch (aliroXMLException $exception) {
00114 aliroRequest::getInstance()->setErrorMessage ($exception->getMessage(), _ALIRO_ERROR_FATAL);
00115 $this->xmlobject = null;
00116 }
00117 if ($this->xmlobject) {
00118 $this->here = dirname($xmlfile).'/';
00119 $this->purifier = new HTMLPurifier;
00120 }
00121 }
00122
00123 public function install () {
00124 if (!$this->xmlobject) return;
00125 try {
00126 $extension = $this->createExtension();
00127 $isUpgrade = $this->getParam($_POST, 'upgrade') ? true : false;
00128 if ($this->extensionExists($extension)) {
00129 if (!$isUpgrade) throw new installerException (T_('cannot be installed - already present'), $extension);
00130
00131 aliroExtensionHandler::getInstance()->removeExtensions($extension->formalname, $isUpgrade);
00132 }
00133 elseif ($isUpgrade) throw new installerException (T_('cannot be upgraded - not presently installed'), $extension);
00134 $this->handler = aliroExtensionHandler::getExtensionTypeHandler($extension->type);
00135 if (!$this->handler) throw new installerException (sprintf(T_('cannot be installed - no handler for type %s'), $extension->type), $extension);
00136 if ('component' == $extension->type) $this->admin = 1;
00137 else $this->admin = $extension->admin;
00138 $extension->store();
00139 $method = 'install_'.$extension->type;
00140 $this->putFilesInPlace($extension);
00141 $this->handleClasses($extension);
00142 if (!$isUpgrade) {
00143 $queries = $this->getXML('install->queries->query');
00144 if ($queries) $this->doQueries($queries);
00145 $jqueries = $this->getXML('install->sql->file');
00146 if ($jqueries) $this->doJQueries($jqueries);
00147 }
00148 if (method_exists($this, $method)) $this->$method($isUpgrade, $extension);
00149 if ($isUpgrade) {
00150 if ($upgradefile = $this->getXML('upgradefile')) {
00151 $this->doPackageCode ($extension, (string) $upgradefile, (string) $upgradefile['class'], 'com_upgrade');
00152 }
00153 }
00154 else {
00155 if ($installfile = $this->getXML('installfile')) {
00156 $this->doPackageCode ($extension, (string) $installfile, (string) $installfile['class'], 'com_install');
00157 }
00158 }
00159 $this->handler->clearCache(('component' != $extension->type));
00160 aliroRequest::getInstance()->setErrorMessage (T_('Installation completed: ').$extension->description, _ALIRO_ERROR_INFORM);
00161 return true;
00162 }
00163 catch (installerException $exception) {
00164 aliroRequest::getInstance()->setErrorMessage (sprintf($exception->getMessage(), basename($this->xmlfile), $exception->extension->formalname), _ALIRO_ERROR_FATAL);
00165 }
00166 catch (databaseException $exception) {
00167 $message = sprintf(T_('Extension XML %s database error on %s at %s'), $this->xmlfile, date('Y-M-d'), date('H:i:s'));
00168 $errorkey = "SQL/{$exception->getCode()}/installer/$exception->dbname/{$exception->getMessage()}/$exception->sql";
00169 aliroErrorRecorder::getInstance()->recordError($message, $errorkey, $message, $exception);
00170 aliroRequest::getInstance()->setErrorMessage ($message, _ALIRO_ERROR_SEVERE);
00171 }
00172 catch (xmlException $exception) {
00173 $message = $exception->getMessage();
00174 aliroErrorRecorder::getInstance()->recordError($message, $message, $message, $exception);
00175 aliroRequest::getInstance()->setErrorMessage ($message, _ALIRO_ERROR_FATAL);
00176 }
00177 return false;
00178 }
00179
00180 protected function extensionExists ($extension) {
00181 return (aliroExtensionHandler::getInstance()->getExtensionByName($extension->formalname)) ? true : false;
00182 }
00183
00184 protected function doPackageCode ($extension, $file, $class, $retro) {
00185 if (false !== strpos($file, '..')) throw new installerException (sprintf(T_('file %s contains illegal ".."'), $file), $extension);
00186 $dofile = $this->handler->getClassPath($extension->formalname, 2).'/'.$file;
00187 if (is_file($dofile)) {
00188 try {
00189 if ($class) {
00190 require_once($dofile);
00191 new $class();
00192 }
00193 else aliroRequest::getInstance()->invokeRetroCode($dofile, $retro);
00194 }
00195 catch (databaseException $exception) {
00196 $message = sprintf(T_('Extension XML %s database error on %s at %s'), $this->xmlfile, date('Y-M-d'), date('H:i:s'));
00197 $errorkey = "SQL/{$exception->getCode()}/installer/$exception->dbname/{$exception->getMessage()}/$exception->sql";
00198 aliroErrorRecorder::getInstance()->recordError($message, $errorkey, $message, $exception);
00199 }
00200 }
00201 }
00202
00203 protected function createExtension () {
00204 $extension = new aliroExtension;
00205 $message = $extension->populateFromXML($this->xmlobject);
00206 if ($message) throw new installerException ($message, $extension);
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 return $extension;
00235 }
00236
00237 protected function getXML ($properties) {
00238 return is_null($this->xmlobject) ? null : $this->xmlobject->getXML($properties);
00239 }
00240
00241 protected function handleClasses ($extension) {
00242 $side = $extension->admin & 2 ? 'admin' : 'user';
00243 $classfiles = $this->getXML('files->filename');
00244 $this->handleClassFiles ($classfiles, $extension, $side);
00245 $classfiles = $this->getXML('classfiles->filename');
00246 $this->handleClassFiles ($classfiles, $extension, $side, true);
00247 if ('component' == $extension->type) {
00248 $classfiles = $this->getXML('administration->files->filename');
00249 $this->handleClassFiles ($classfiles, $extension, 'admin');
00250 $classfiles = $this->getXML('administration->classfiles->filename');
00251 $this->handleClassFiles ($classfiles, $extension, 'admin', true);
00252 }
00253 smartAdminClassMapper::getInstance()->clearCache();
00254 smartClassMapper::getInstance()->clearCache();
00255 }
00256
00257 protected function handleClassFiles ($classfiles, $extension, $side, $classRequired=false) {
00258 if ($classfiles) {
00259 $database = aliroCoreDatabase::getInstance();
00260 foreach ($classfiles as $classfile) {
00261 $classes = explode(',', (string) $classfile['classes']);
00262 $filename = (string) $classfile;
00263 $filedir = dirname($filename);
00264 $filemap = ('.' == $filedir ? '' : $filedir.'/').basename($filename, '.php');
00265 foreach ($classes as $class) {
00266 $class = trim($class);
00267 if (!$class) {
00268 if ($classRequired) aliroRequest::getInstance()->setErrorMessage (sprintf(T_('Installer error: XML file %s for extension %s - filename %s has no valid classes attribute'), basename($this->xmlfile), $extension->formalname, $filename), _ALIRO_ERROR_SEVERE);
00269 continue;
00270 }
00271 $database->doSQL("INSERT INTO #__classmap VALUES (0, '$extension->type', '$extension->formalname', '$side', '$filemap', '$class')");
00272 }
00273 }
00274 }
00275 }
00276
00277 protected function putFilesInPlace ($extension) {
00278 $xmlfilename = basename($this->xmlfile);
00279 if (!$this->handler->createDirectory($extension->formalname, $extension->admin)) {
00280 throw new installerException (sprintf(T_('unable to create user directory for %s %s'), $extension->type, $extension->formalname), $extension);
00281 }
00282 $side = ($extension->admin & 2) ? 'admin' : 'user';
00283 $dirpath = $this->handler->getPath($extension->formalname, $extension->admin);
00284 $classpath = $this->handler->getClassPath($extension->formalname, $extension->admin);
00285 $this->moveFiles($this->getXML('classfiles->filename'), $classpath);
00286 $this->moveFiles($this->getXML('files->filename'), $dirpath, $this->getXML('files->[folder]'));
00287 $this->moveFiles($this->getXML('images->filename'), $dirpath);
00288 $this->moveFiles($this->getXML('css->filename'), $dirpath);
00289 $this->moveFiles($this->getXML('media->filename'), $this->absolute_path.'/images/stories/');
00290 if ('component' == $extension->type) {
00291 if (!$this->handler->createDirectory($extension->formalname, 2)) {
00292 throw new installerException (sprintf(T_('unable to create user directory for %s %s'), $extension->type, $extension->formalname), $extension);
00293 }
00294 $dirpath = $this->handler->getPath($extension->formalname, 2);
00295 $classpath = $this->handler->getClassPath($extension->formalname, 2);
00296 $this->moveFiles($this->getXML('administration->files->filename'), $dirpath, $this->getXML('administration->files->[folder]'));
00297 $this->moveFiles($this->getXML('administration->classfiles->filename'), $classpath);
00298 $this->moveFiles($this->getXML('administration->images->filename'), $dirpath);
00299 $this->moveFiles(array($this->getXML('installfile')), $classpath);
00300 $this->moveFiles(array($this->getXML('uninstallfile')), $classpath);
00301 $this->moveFiles(array($this->getXML('upgradefile')), $classpath);
00302 $this->moveFiles(array($xmlfilename), $this->handler->getXMLPath($extension->formalname, 2));
00303 }
00304 $this->moveFiles(array($xmlfilename), $this->handler->getXMLPath($extension->formalname, $extension->admin));
00305 aliroCoreDatabase::getInstance()->doSQL("UPDATE #__extensions SET xmlfile = '{$this->handler->getXMLRelativePath($extension->formalname, $extension->admin)}/{$xmlfilename}' WHERE formalname = '$extension->formalname'");
00306 }
00307
00308 protected function moveFiles ($files, $path, $subdir='') {
00309 $fromdir = $subdir ? $this->here.$subdir.'/' : $this->here;
00310 if ($files) {
00311 $fmanager = aliroFileManager::getInstance();
00312 foreach ($files as $file) {
00313 $filename = trim((string) $file);
00314 if ($filename) {
00315 if (false !== strpos($filename, '..')) {
00316 throw new installerException (sprintf(T_('file %s contains illegal ".."'), $filename), $extension);
00317 }
00318 else $fmanager->forceCopy($fromdir.$filename, $path.'/'.$filename, true);
00319 }
00320 }
00321 }
00322 }
00323
00324 protected function doQueries ($queries) {
00325 $database = aliroDatabase::getInstance();
00326 foreach ($queries as $query) if ($query = trim((string)$query)) $database->doSQL($query);
00327 }
00328
00329 protected function doJQueries ($jqueries) {
00330 $database = aliroDatabase::getInstance();
00331 $subdir = $this->getXML('administration->files->[folder]').'/';
00332 foreach ($jqueries as $query) {
00333 if ($query = trim((string)$query)) {
00334 $realquery = @file_get_contents($this->here.$subdir.$query);
00335 if ($realquery) {
00336 $database->setQuery($realquery);
00337 $database->query_batch();
00338 }
00339 }
00340 }
00341 }
00342
00343 protected function createComponentMenu ($item, $name, $parent, $toplevel=false) {
00344 $menuitem = new aliroAdminMenu();
00345 $menuitem->name = $this->purifier->purify((string) $item);
00346 $menuitem->parent = $toplevel;
00347 $link = "index.php?option=$name";
00348 if ($toplevel AND ($linkdetail = (string) $item['link'])) {
00349 if ('&' == $linkdetail[0]) $link .= $linkdetail;
00350 else $link = 'index.php?'.$linkdetail;
00351 }
00352 elseif ($toplevel AND ($task = (string) $item['task'])) $link .= '&task='.$task;
00353 $menuitem->link = $link;
00354 $menuitem->type = 'components';
00355 $menuitem->published = 1;
00356 $menuitem->parent = $parent;
00357 $menuitem->component = $name;
00358 $menuitem->ordering = $toplevel ? $this->submenuordering++ : 0;
00359 $menuitem->store();
00360 return $menuitem->id;
00361 }
00362
00363 protected function install_component ($isUpgrade, $extension) {
00364 $mainmenu = $this->getXML('administration->menu');
00365 $component = new aliroComponent();
00366 $component->name = ($mainmenu ? $this->purifier->purify((string) $mainmenu) : $extension->name);
00367 $component->option = $component->extformalname = $extension->formalname;
00368 $component->ordering = 0;
00369 $component->class = $this->xmlobject->baseAttribute('userclass');
00370 $component->adminclass = $this->xmlobject->baseAttribute('adminclass');
00371 $component->menuclass = $this->xmlobject->baseAttribute('menuclass');
00372 $component->params = '';
00373 $component->store();
00374 if ($mainmenu) {
00375 $topid = $this->createComponentMenu ($mainmenu, $extension->formalname, aliroAdminMenuHandler::getInstance()->baseComponentMenu());
00376 $submenus = $this->getXML('administration->submenu->menu');
00377 $this->submenuordering = 1;
00378 if ($submenus) foreach ($submenus as $submenu) {
00379 $this->createComponentMenu ($submenu, $extension->formalname, $topid, true);
00380 }
00381 }
00382 aliroAdminMenuHandler::getInstance()->clearCache(true);
00383 }
00384
00385 public function removeComponent ($handler, $extension) {
00386 try {
00387 $classpath = $handler->getClassPath($extension->formalname, 2);
00388 if ($uninstallfile = $this->getXML('uninstallfile')) {
00389 $this->handler = $handler;
00390 $this->doPackageCode ($extension, (string) $uninstallfile, (string) $uninstallfile['class'], 'com_uninstall');
00391 }
00392 $queries = $this->getXML('uninstall->queries->query');
00393 if ($queries) foreach ($queries as $query) {
00394 aliroDatabase::getInstance()->doSQL((string) $query);
00395 }
00396 }
00397 catch (databaseException $exception) {
00398
00399 }
00400 }
00401
00402 protected function install_module ($isUpgrade, $extension) {
00403 $module = new aliroModule();
00404 $module->title = $extension->name;
00405 $module->ordering = 99;
00406 $module->position = call_user_func(array(aliroTemplateHandler::getInstance()->getDefaultUserTemplateClass(), 'defaultModulePosition'));
00407 $module->showtitle = 1;
00408 $module->admin = $extension->admin;
00409 $module->module = $extension->formalname;
00410 $module->class = $this->xmlobject->baseAttribute('userclass');
00411 $module->adminclass = $this->xmlobject->baseAttribute('adminclass');
00412 $module->published = ('yes' == $this->xmlobject->baseAttribute('published')) ? 1 : 0;
00413 $module->store();
00414 aliroCoreDatabase::getInstance()->doSQL("INSERT INTO #__modules_menu VALUES ('$module->id', 0)");
00415 }
00416
00417 protected function install_mambot ($isUpgrade, $extension) {
00418 $mambot = new aliroMambot();
00419 $mambot->name = $extension->name;
00420 $mambot->ordering = 99;
00421 $mambot->element = $extension->formalname;
00422 $mambot->class = $this->xmlobject->baseAttribute('userclass');
00423 $mambot->published = ('yes' == $this->xmlobject->baseAttribute('published')) ? 1 : 0;
00424 if ($triggers = $this->xmlobject->baseAttribute('triggers')) {
00425 $mambot->triggers = $triggers;
00426 $mambot->store();
00427 }
00428 else throw new installerException (T_('is plugin but has no triggers'), $extension);
00429 }
00430
00431 }