1 <?php
  2   3   4   5   6   7   8 
  9 
 10 defined('JPATH_PLATFORM') or die;
 11 
 12 use Joomla\Utilities\ArrayHelper;
 13 
 14 jimport('joomla.filesystem.folder');
 15 
 16  17  18  19  20 
 21 class JInstallerAdapterModule extends JInstallerAdapter
 22 {
 23      24  25  26  27  28 
 29     protected $clientId;
 30 
 31      32  33  34  35  36 
 37     protected $scriptElement = null;
 38 
 39      40  41  42  43  44  45  46 
 47     protected function checkExistingExtension()
 48     {
 49         try
 50         {
 51             $this->currentExtensionId = $this->extension->find(
 52                 array(
 53                     'element'   => $this->element,
 54                     'type'      => $this->type,
 55                     'client_id' => $this->clientId,
 56                 )
 57             );
 58         }
 59         catch (RuntimeException $e)
 60         {
 61             
 62             throw new RuntimeException(
 63                 JText::sprintf(
 64                     'JLIB_INSTALLER_ABORT_ROLLBACK',
 65                     JText::_('JLIB_INSTALLER_' . $this->route),
 66                     $e->getMessage()
 67                 ),
 68                 $e->getCode(),
 69                 $e
 70             );
 71         }
 72     }
 73 
 74      75  76  77  78  79  80  81 
 82     protected function copyBaseFiles()
 83     {
 84         
 85         if ($this->parent->parseFiles($this->getManifest()->files, -1) === false)
 86         {
 87             throw new RuntimeException(JText::_('JLIB_INSTALLER_ABORT_MOD_COPY_FILES'));
 88         }
 89 
 90         
 91         if ($this->manifest_script)
 92         {
 93             $path['src']  = $this->parent->getPath('source') . '/' . $this->manifest_script;
 94             $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->manifest_script;
 95 
 96             if ($this->parent->isOverwrite() || !file_exists($path['dest']))
 97             {
 98                 if (!$this->parent->copyFiles(array($path)))
 99                 {
100                     
101                     throw new RuntimeException(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_MANIFEST'));
102                 }
103             }
104         }
105     }
106 
107     108 109 110 111 112 113 114 
115     protected function finaliseInstall()
116     {
117         
118         $update = JTable::getInstance('update');
119         $uid    = $update->find(
120             array(
121                 'element'   => $this->element,
122                 'type'      => 'module',
123                 'client_id' => $this->clientId,
124             )
125         );
126 
127         if ($uid)
128         {
129             $update->delete($uid);
130         }
131 
132         
133         if ($this->route !== 'discover_install')
134         {
135             if (!$this->parent->copyManifest(-1))
136             {
137                 
138                 throw new RuntimeException(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_COPY_SETUP'));
139             }
140         }
141     }
142 
143     144 145 146 147 148 149 150 151 
152     public function getElement($element = null)
153     {
154         if (!$element)
155         {
156             if (count($this->getManifest()->files->children()))
157             {
158                 foreach ($this->getManifest()->files->children() as $file)
159                 {
160                     if ((string) $file->attributes()->module)
161                     {
162                         $element = strtolower((string) $file->attributes()->module);
163 
164                         break;
165                     }
166                 }
167             }
168         }
169 
170         return $element;
171     }
172 
173     174 175 176 177 178 179 180 181 
182     public function loadLanguage($path = null)
183     {
184         $source = $this->parent->getPath('source');
185         $client = $this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE;
186 
187         if (!$source)
188         {
189             $this->parent->setPath('source', $client . '/modules/' . $this->parent->extension->element);
190         }
191 
192         $this->setManifest($this->parent->getManifest());
193 
194         if ($this->getManifest()->files)
195         {
196             $extension = $this->getElement();
197 
198             if ($extension)
199             {
200                 $source = $path ?: ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $extension;
201                 $folder = (string) $this->getManifest()->files->attributes()->folder;
202 
203                 if ($folder && file_exists($path . '/' . $folder))
204                 {
205                     $source = $path . '/' . $folder;
206                 }
207 
208                 $client = (string) $this->getManifest()->attributes()->client;
209                 $this->doLoadLanguage($extension, $source, constant('JPATH_' . strtoupper($client)));
210             }
211         }
212     }
213 
214     215 216 217 218 219 220 
221     protected function parseOptionalTags()
222     {
223         
224         $this->parent->parseMedia($this->getManifest()->media, $this->clientId);
225         $this->parent->parseLanguages($this->getManifest()->languages, $this->clientId);
226     }
227 
228     229 230 231 232 233 234 
235     public function prepareDiscoverInstall()
236     {
237         $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
238         $manifestPath = $client->path . '/modules/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml';
239         $this->parent->manifest = $this->parent->isManifest($manifestPath);
240         $this->parent->setPath('manifest', $manifestPath);
241         $this->setManifest($this->parent->getManifest());
242     }
243 
244     245 246 247 248 249 250 251 
252     protected function setupInstallPaths()
253     {
254         
255         $cname = (string) $this->getManifest()->attributes()->client;
256 
257         if ($cname)
258         {
259             
260             $client = JApplicationHelper::getClientInfo($cname, true);
261 
262             if ($client === false)
263             {
264                 throw new RuntimeException(
265                     JText::sprintf(
266                         'JLIB_INSTALLER_ABORT_MOD_UNKNOWN_CLIENT',
267                         JText::_('JLIB_INSTALLER_' . $this->route),
268                         $client->name
269                     )
270                 );
271             }
272 
273             $basePath = $client->path;
274             $this->clientId = $client->id;
275         }
276         else
277         {
278             
279             $basePath = JPATH_SITE;
280             $this->clientId = 0;
281         }
282 
283         
284         if (empty($this->element))
285         {
286             throw new RuntimeException(
287                 JText::sprintf(
288                     'JLIB_INSTALLER_ABORT_MOD_INSTALL_NOFILE',
289                     JText::_('JLIB_INSTALLER_' . $this->route)
290                 )
291             );
292         }
293 
294         $this->parent->setPath('extension_root', $basePath . '/modules/' . $this->element);
295     }
296 
297     298 299 300 301 302 303 304 
305     protected function storeExtension()
306     {
307         
308         if ($this->route === 'discover_install')
309         {
310             $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
311 
312             $this->extension->manifest_cache = json_encode($manifest_details);
313             $this->extension->state = 0;
314             $this->extension->name = $manifest_details['name'];
315             $this->extension->enabled = 1;
316             $this->extension->params = $this->parent->getParams();
317 
318             if (!$this->extension->store())
319             {
320                 
321                 throw new RuntimeException(JText::_('JLIB_INSTALLER_ERROR_MOD_DISCOVER_STORE_DETAILS'));
322             }
323 
324             return;
325         }
326 
327         
328         if ($this->currentExtensionId)
329         {
330             if (!$this->parent->isOverwrite())
331             {
332                 
333                 throw new RuntimeException(
334                     JText::sprintf(
335                         'JLIB_INSTALLER_ABORT_MOD_INSTALL_ALLREADY_EXISTS',
336                         JText::_('JLIB_INSTALLER_' . $this->route),
337                         $this->name
338                     )
339                 );
340             }
341 
342             
343             $this->extension->load($this->currentExtensionId);
344 
345             
346             $this->extension->name = $this->name;
347 
348             
349             $this->extension->manifest_cache = $this->parent->generateManifestCache();
350 
351             if (!$this->extension->store())
352             {
353                 
354                 throw new RuntimeException(
355                     JText::sprintf(
356                         'JLIB_INSTALLER_ABORT_MOD_ROLLBACK',
357                         JText::_('JLIB_INSTALLER_' . $this->route),
358                         $this->extension->getError()
359                     )
360                 );
361             }
362         }
363         else
364         {
365             $this->extension->name    = $this->name;
366             $this->extension->type    = 'module';
367             $this->extension->element = $this->element;
368 
369             
370             $this->extension->folder    = '';
371             $this->extension->enabled   = 1;
372             $this->extension->protected = 0;
373             $this->extension->access    = $this->clientId == 1 ? 2 : 0;
374             $this->extension->client_id = $this->clientId;
375             $this->extension->params    = $this->parent->getParams();
376 
377             
378             $this->extension->custom_data    = '';
379             $this->extension->system_data    = '';
380             $this->extension->manifest_cache = $this->parent->generateManifestCache();
381 
382             if (!$this->extension->store())
383             {
384                 
385                 throw new RuntimeException(
386                     JText::sprintf(
387                         'JLIB_INSTALLER_ABORT_MOD_ROLLBACK',
388                         JText::_('JLIB_INSTALLER_' . $this->route),
389                         $this->extension->getError()
390                     )
391                 );
392             }
393 
394             
395             
396             $this->parent->pushStep(
397                 array(
398                     'type' => 'extension',
399                     'extension_id' => $this->extension->extension_id,
400                 )
401             );
402 
403             
404             $name = preg_replace('#[\*?]#', '', JText::_($this->name));
405 
406             
407             $module            = JTable::getInstance('module');
408             $module->title     = $name;
409             $module->content   = '';
410             $module->module    = $this->element;
411             $module->access    = '1';
412             $module->showtitle = '1';
413             $module->params    = '';
414             $module->client_id = $this->clientId;
415             $module->language  = '*';
416 
417             $module->store();
418         }
419     }
420 
421     422 423 424 425 426 427 
428     public function discover()
429     {
430         $results = array();
431         $site_list = JFolder::folders(JPATH_SITE . '/modules');
432         $admin_list = JFolder::folders(JPATH_ADMINISTRATOR . '/modules');
433         $site_info = JApplicationHelper::getClientInfo('site', true);
434         $admin_info = JApplicationHelper::getClientInfo('administrator', true);
435 
436         foreach ($site_list as $module)
437         {
438             if (file_exists(JPATH_SITE . "/modules/$module/$module.xml"))
439             {
440                 $manifest_details = JInstaller::parseXMLInstallFile(JPATH_SITE . "/modules/$module/$module.xml");
441                 $extension = JTable::getInstance('extension');
442                 $extension->set('type', 'module');
443                 $extension->set('client_id', $site_info->id);
444                 $extension->set('element', $module);
445                 $extension->set('folder', '');
446                 $extension->set('name', $module);
447                 $extension->set('state', -1);
448                 $extension->set('manifest_cache', json_encode($manifest_details));
449                 $extension->set('params', '{}');
450                 $results[] = clone $extension;
451             }
452         }
453 
454         foreach ($admin_list as $module)
455         {
456             if (file_exists(JPATH_ADMINISTRATOR . "/modules/$module/$module.xml"))
457             {
458                 $manifest_details = JInstaller::parseXMLInstallFile(JPATH_ADMINISTRATOR . "/modules/$module/$module.xml");
459                 $extension = JTable::getInstance('extension');
460                 $extension->set('type', 'module');
461                 $extension->set('client_id', $admin_info->id);
462                 $extension->set('element', $module);
463                 $extension->set('folder', '');
464                 $extension->set('name', $module);
465                 $extension->set('state', -1);
466                 $extension->set('manifest_cache', json_encode($manifest_details));
467                 $extension->set('params', '{}');
468                 $results[] = clone $extension;
469             }
470         }
471 
472         return $results;
473     }
474 
475     476 477 478 479 480 481 
482     public function refreshManifestCache()
483     {
484         $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
485         $manifestPath = $client->path . '/modules/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml';
486         $this->parent->manifest = $this->parent->isManifest($manifestPath);
487         $this->parent->setPath('manifest', $manifestPath);
488         $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
489         $this->parent->extension->manifest_cache = json_encode($manifest_details);
490         $this->parent->extension->name = $manifest_details['name'];
491 
492         if ($this->parent->extension->store())
493         {
494             return true;
495         }
496         else
497         {
498             JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
499 
500             return false;
501         }
502     }
503 
504     505 506 507 508 509 510 511 512 
513     public function uninstall($id)
514     {
515         $retval = true;
516         $db     = $this->db;
517 
518         
519         
520         if (!$this->extension->load((int) $id) || $this->extension->element === '')
521         {
522             JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_ERRORUNKOWNEXTENSION'), JLog::WARNING, 'jerror');
523 
524             return false;
525         }
526 
527         
528         
529         if ($this->extension->protected)
530         {
531             JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_WARNCOREMODULE', $this->extension->name), JLog::WARNING, 'jerror');
532 
533             return false;
534         }
535 
536         537 538 539 
540         if ($this->extension->package_id && !$this->parent->isPackageUninstall() && !$this->canUninstallPackageChild($this->extension->package_id))
541         {
542             JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_CANNOT_UNINSTALL_CHILD_OF_PACKAGE', $this->extension->name), JLog::WARNING, 'jerror');
543 
544             return false;
545         }
546 
547         
548         $element = $this->extension->element;
549         $client  = JApplicationHelper::getClientInfo($this->extension->client_id);
550 
551         if ($client === false)
552         {
553             $this->parent->abort(
554                 JText::sprintf(
555                     'JLIB_INSTALLER_ERROR_MOD_UNINSTALL_UNKNOWN_CLIENT',
556                     $this->extension->client_id
557                 )
558             );
559 
560             return false;
561         }
562 
563         $this->parent->setPath('extension_root', $client->path . '/modules/' . $element);
564 
565         $this->parent->setPath('source', $this->parent->getPath('extension_root'));
566 
567         
568         
569         $this->parent->findManifest();
570         $this->setManifest($this->parent->getManifest());
571 
572         
573         $this->loadLanguage(($this->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $element);
574 
575         
576         $this->scriptElement = $this->getManifest()->scriptfile;
577         $manifestScript      = (string) $this->getManifest()->scriptfile;
578 
579         if ($manifestScript)
580         {
581             $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript;
582 
583             
584             $classname = $element . 'InstallerScript';
585 
586             JLoader::register($classname, $manifestScriptFile);
587 
588             if (class_exists($classname))
589             {
590                 
591                 $this->parent->manifestClass = new $classname($this);
592 
593                 
594                 $this->set('manifest_script', $manifestScript);
595             }
596         }
597 
598         try
599         {
600             $this->triggerManifestScript('uninstall');
601         }
602         catch (RuntimeException $e)
603         {
604             
605         }
606 
607         if (!($this->getManifest() instanceof SimpleXMLElement))
608         {
609             
610             JFolder::delete($this->parent->getPath('extension_root'));
611             JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_INVALID_NOTFOUND_MANIFEST'), JLog::WARNING, 'jerror');
612 
613             return false;
614         }
615 
616         
617         try
618         {
619             $this->parseQueries();
620         }
621         catch (RuntimeException $e)
622         {
623             
624             JLog::add($e->getMessage(), JLog::WARNING, 'jerror');
625             $retval = false;
626         }
627 
628         
629         $query = $db->getQuery(true)
630             ->delete('#__schemas')
631             ->where('extension_id = ' . $this->extension->extension_id);
632         $db->setQuery($query);
633         $db->execute();
634 
635         
636         $this->parent->removeFiles($this->getManifest()->media);
637         $this->parent->removeFiles($this->getManifest()->languages, $this->extension->client_id);
638 
639         
640         $query->clear()
641             ->select($db->quoteName('id'))
642             ->from($db->quoteName('#__modules'))
643             ->where($db->quoteName('module') . ' = ' . $db->quote($this->extension->element))
644             ->where($db->quoteName('client_id') . ' = ' . (int) $this->extension->client_id);
645         $db->setQuery($query);
646 
647         try
648         {
649             $modules = $db->loadColumn();
650         }
651         catch (RuntimeException $e)
652         {
653             $modules = array();
654         }
655 
656         
657         if (count($modules))
658         {
659             
660             $modules = ArrayHelper::toInteger($modules);
661             $modID = implode(',', $modules);
662 
663             
664             $query = $db->getQuery(true)
665                 ->delete($db->quoteName('#__modules_menu'))
666                 ->where($db->quoteName('moduleid') . ' IN (' . $modID . ')');
667             $db->setQuery($query);
668 
669             try
670             {
671                 $db->execute();
672             }
673             catch (RuntimeException $e)
674             {
675                 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION', $db->stderr(true)), JLog::WARNING, 'jerror');
676                 $retval = false;
677             }
678 
679             
680             
681             $module = JTable::getInstance('Module');
682 
683             foreach ($modules as $modInstanceId)
684             {
685                 $module->load($modInstanceId);
686 
687                 if (!$module->delete())
688                 {
689                     JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION', $module->getError()), JLog::WARNING, 'jerror');
690                     $retval = false;
691                 }
692             }
693         }
694 
695         
696         $this->extension->delete($this->extension->extension_id);
697         $query = $db->getQuery(true)
698             ->delete($db->quoteName('#__modules'))
699             ->where($db->quoteName('module') . ' = ' . $db->quote($this->extension->element))
700             ->where($db->quote('client_id') . ' = ' . $this->extension->client_id);
701         $db->setQuery($query);
702 
703         try
704         {
705             
706             $db->execute();
707         }
708         catch (RuntimeException $e)
709         {
710             
711         }
712 
713         
714         if (!JFolder::delete($this->parent->getPath('extension_root')))
715         {
716             
717             $retval = false;
718         }
719 
720         return $retval;
721     }
722 
723     724 725 726 727 728 729 730 731 732 
733     protected function ($arg)
734     {
735         
736         $db = $this->parent->getDbo();
737 
738         
739         $query = $db->getQuery(true)
740             ->delete($db->quoteName('#__modules_menu'))
741             ->where($db->quoteName('moduleid') . ' = ' . (int) $arg['id']);
742         $db->setQuery($query);
743 
744         try
745         {
746             return $db->execute();
747         }
748         catch (RuntimeException $e)
749         {
750             return false;
751         }
752     }
753 
754     755 756 757 758 759 760 761 762 763 
764     protected function _rollback_module($arg)
765     {
766         
767         $db = $this->parent->getDbo();
768 
769         
770         $query = $db->getQuery(true)
771             ->delete($db->quoteName('#__modules'))
772             ->where($db->quoteName('id') . ' = ' . (int) $arg['id']);
773         $db->setQuery($query);
774 
775         try
776         {
777             return $db->execute();
778         }
779         catch (RuntimeException $e)
780         {
781             return false;
782         }
783     }
784 }
785 
786 787 788 789 790 791 792 
793 class JInstallerModule extends JInstallerAdapterModule
794 {
795 }
796