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