Completed
Pull Request — develop (#833)
by Thong Tran
05:33
created

Com_RedcoreInstallerScript::insertSiteDomain()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 35
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 35
rs 8.5806
cc 4
eloc 18
nc 4
nop 0
1
<?php
2
/**
3
 * @package     Redcore
4
 * @subpackage  Model
5
 *
6
 * @copyright   Copyright (C) 2008 - 2016 redCOMPONENT.com. All rights reserved.
7
 * @license     GNU General Public License version 2 or later, see LICENSE.
8
 */
9
10
use Joomla\Registry\Registry;
11
12
defined('_JEXEC') or die;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
13
14
/**
15
 * Custom installation of redCORE
16
 *
17
 * @package     Redcore
18
 * @subpackage  Install
19
 * @since       1.0
20
 */
21
class Com_RedcoreInstallerScript
22
{
23
	/**
24
	 * Status of the installation
25
	 *
26
	 * @var  stdClass
27
	 */
28
	public $status;
29
30
	/**
31
	 * Show component info after install / update
32
	 *
33
	 * @var  boolean
34
	 */
35
	public $showComponentInfo = true;
36
37
	/**
38
	 * Installer instance
39
	 *
40
	 * @var  JInstaller
41
	 */
42
	public $installer;
43
44
	/**
45
	 * Extension element name
46
	 *
47
	 * @var  string
48
	 */
49
	protected $extensionElement = '';
50
51
	/**
52
	 * Manifest of the extension being processed
53
	 *
54
	 * @var  SimpleXMLElement
55
	 */
56
	protected $manifest;
57
58
	/**
59
	 * Old version according to manifest
60
	 *
61
	 * @var  string
62
	 */
63
	protected $oldVersion = '0.0.0';
64
65
	/**
66
	 * Get the common JInstaller instance used to install all the extensions
67
	 *
68
	 * @return JInstaller The JInstaller object
69
	 */
70
	public function getInstaller()
71
	{
72
		if (null === $this->installer)
73
		{
74
			$this->installer = new JInstaller;
75
		}
76
77
		return $this->installer;
78
	}
79
80
	/**
81
	 * Getter with manifest cache support
82
	 *
83
	 * @param   JInstallerAdapter  $parent  Parent object
84
	 *
85
	 * @return  SimpleXMLElement
86
	 */
87
	protected function getManifest($parent)
88
	{
89
		if (null === $this->manifest)
90
		{
91
			$this->loadManifest($parent);
92
		}
93
94
		return $this->manifest;
95
	}
96
97
	/**
98
	 * Method to run before an install/update/uninstall method
99
	 *
100
	 * @param   string             $type    Type of change (install, update or discover_install)
101
	 * @param   JInstallerAdapter  $parent  Class calling this method
102
	 *
103
	 * @return  boolean
104
	 *
105
	 * @throws  Exception
106
	 */
107
	public function preflight($type, $parent)
108
	{
109
		$this->installRedcore($type, $parent);
110
		$this->loadRedcoreLibrary();
111
		$this->loadRedcoreLanguage();
112
		$manifest               = $this->getManifest($parent);
113
		$extensionType          = $manifest->attributes()->type;
114
		$this->extensionElement = $this->getElement($parent, $manifest);
115
116
		// Reads current (old) version from manifest
117
		$db      = JFactory::getDbo();
118
		$version = $db->setQuery(
119
			$db->getQuery(true)
120
				->select($db->qn('s.version_id'))
121
				->from($db->qn('#__schemas', 's'))
122
				->join('inner', $db->qn('#__extensions', 'e') . ' ON ' . $db->qn('e.extension_id') . ' = ' . $db->qn('s.extension_id'))
123
				->where($db->qn('e.element') . ' = ' . $db->q($this->extensionElement))
124
		)
125
			->loadResult();
126
127
		if (!empty($version))
128
		{
129
			$this->oldVersion = (string) $version;
130
		}
131
132
		if ($extensionType == 'component' && in_array($type, array('install', 'update', 'discover_install')))
0 ignored issues
show
introduced by
The condition $extensionType == 'component' is always false.
Loading history...
133
		{
134
			// Update SQL pre-processing
135
			if ($type == 'update')
136
			{
137
				if (!$this->preprocessUpdates($parent))
138
				{
139
					return false;
140
				}
141
			}
142
143
			// In case we are installing redcore
144
			if (get_called_class() === 'Com_RedcoreInstallerScript')
145
			{
146
				if (!$this->checkComponentVersion($this->getRedcoreComponentFolder(), __DIR__, 'redcore.xml'))
147
				{
148
					throw new RuntimeException(JText::_('COM_REDCORE_INSTALL_ERROR_OLDER_VERSION'));
149
				}
150
151
				if (!class_exists('RComponentHelper'))
152
				{
153
					$searchPaths = array(
154
						// Discover install
155
						JPATH_LIBRARIES . '/redcore/component',
156
						// Install
157
						__DIR__ . '/redCORE/libraries/redcore/component',
158
						__DIR__ . '/libraries/redcore/component'
159
					);
160
161
					$componentHelper = JPath::find($searchPaths, 'helper.php');
162
163
					if ($componentHelper)
164
					{
165
						require_once $componentHelper;
166
					}
167
				}
168
			}
169
170
			$requirements = array();
171
172
			if (method_exists('RComponentHelper', 'checkComponentRequirements'))
173
			{
174
				$requirements = RComponentHelper::checkComponentRequirements($manifest->requirements);
175
			}
176
177
			if (!empty($requirements))
178
			{
179
				foreach ($requirements as $key => $requirement)
180
				{
181
					foreach ($requirement as $checked)
182
					{
183
						if (!$checked['status'])
184
						{
185
							// In case redCORE cannot be installed we do not have the language string
186
							if (get_called_class() === 'Com_RedcoreInstallerScript')
187
							{
188
								$this->loadRedcoreLanguage(__DIR__);
189
								$checked['name'] = JText::_($checked['name']);
190
							}
191
192
							$messageKey = $key == 'extensions'
193
								? 'COM_REDCORE_INSTALL_ERROR_REQUIREMENTS_EXTENSIONS'
194
								: 'COM_REDCORE_INSTALL_ERROR_REQUIREMENTS';
195
196
							throw new RuntimeException(JText::sprintf($messageKey, $checked['name'], $checked['required'], $checked['current']));
197
						}
198
					}
199
				}
200
			}
201
		}
202
203
		return true;
204
	}
205
206
	/**
207
	 * Method to install the component
208
	 *
209
	 * @param   JInstallerAdapter  $parent  Class calling this method
210
	 *
211
	 * @return  boolean          True on success
212
	 */
213
	public function install($parent)
214
	{
215
		// Common tasks for install or update
216
		$this->installOrUpdate($parent);
217
218
		return true;
219
	}
220
221
	/**
222
	 * Method to install the component
223
	 *
224
	 * @param   JInstallerAdapter  $parent  Class calling this method
225
	 *
226
	 * @return  boolean                     True on success
227
	 */
228
	public function installOrUpdate($parent)
229
	{
230
		// Install extensions
231
		// We have already installed redCORE library on preflight so we will not do it again
232
		if (get_called_class() !== 'Com_RedcoreInstallerScript')
233
		{
234
			$this->installLibraries($parent);
235
		}
236
237
		$this->loadRedcoreLibrary();
238
		$this->installMedia($parent);
239
		$this->installWebservices($parent);
240
		$this->installModules($parent);
241
		$this->installPlugins($parent);
242
		$this->installTemplates($parent);
243
		$this->installCli($parent);
244
245
		return true;
246
	}
247
248
	/**
249
	 * Method to process SQL updates previous to the install process
250
	 *
251
	 * @param   JInstallerAdapter  $parent  Class calling this method
252
	 *
253
	 * @return  boolean          True on success
254
	 */
255
	public function preprocessUpdates($parent)
256
	{
257
		$manifest = $parent->get('manifest');
258
259
		if (isset($manifest->update))
260
		{
261
			if (isset($manifest->update->attributes()->folder))
262
			{
263
				$path       = $manifest->update->attributes()->folder;
264
				$sourcePath = $parent->getParent()->getPath('source');
265
266
				if (isset($manifest->update->pre, $manifest->update->pre->schemas))
267
				{
268
					$schemaPaths = $manifest->update->pre->schemas->children();
269
270
					if (count($schemaPaths))
271
					{
272
						// If it just upgraded redCORE to a newer version using RFactory for database, it forces using the redCORE database drivers
273
						if (substr(get_class(JFactory::$database), 0, 1) == 'J' && $this->extensionElement != 'com_redcore')
274
						{
275
							RFactory::$database = null;
276
							JFactory::$database = RFactory::getDbo();
277
						}
278
279
						$db = JFactory::getDbo();
280
281
						$dbDriver   = strtolower($db->name);
282
						$dbDriver   = $dbDriver == 'mysqli' ? 'mysql' : $dbDriver;
283
						$schemaPath = '';
284
285
						foreach ($schemaPaths as $entry)
286
						{
287
							if (isset($entry->attributes()->type))
288
							{
289
								$uDriver = strtolower($entry->attributes()->type);
290
291
								if ($uDriver == 'mysqli')
292
								{
293
									$uDriver = 'mysql';
294
								}
295
296
								if ($uDriver == $dbDriver)
297
								{
298
									$schemaPath = (string) $entry;
299
									break;
300
								}
301
							}
302
						}
303
304
						if ($schemaPath != '')
0 ignored issues
show
introduced by
The condition $schemaPath != '' is always false.
Loading history...
305
						{
306
							$files = str_replace('.sql', '', JFolder::files($sourcePath . '/' . $path . '/' . $schemaPath, '\.sql$'));
307
							usort($files, 'version_compare');
308
309
							if (count($files))
310
							{
311
								foreach ($files as $file)
312
								{
313
									if (version_compare($file, $this->oldVersion) > 0)
314
									{
315
										$buffer  = file_get_contents($sourcePath . '/' . $path . '/' . $schemaPath . '/' . $file . '.sql');
316
										$queries = RHelperDatabase::splitSQL($buffer);
317
318
										if (count($queries))
319
										{
320
											foreach ($queries as $query)
321
											{
322
												if ($query != '' && $query{0} != '#')
323
												{
324
													$db->setQuery($query);
325
326
													if (!$db->execute(true))
327
													{
328
														JLog::add(
329
															JText::sprintf('JLIB_INSTALLER_ERROR_SQL_ERROR', $db->stderr(true)),
330
															JLog::WARNING,
331
															'jerror'
332
														);
333
334
														return false;
335
													}
336
												}
337
											}
338
										}
339
									}
340
								}
341
							}
342
						}
343
					}
344
				}
345
			}
346
		}
347
348
		return true;
349
	}
350
351
	/**
352
	 * Method to process PHP update files defined in the manifest file
353
	 *
354
	 * @param   JInstallerAdapter  $parent              Class calling this method
355
	 * @param   bool               $executeAfterUpdate  The name of the function to execute
356
	 *
357
	 * @return  boolean          True on success
358
	 */
359
	public function phpUpdates($parent, $executeAfterUpdate)
360
	{
361
		$manifest = $parent->get('manifest');
362
363
		if (isset($manifest->update))
364
		{
365
			if (isset($manifest->update->php) && isset($manifest->update->php->path))
366
			{
367
				$updatePath = (string) $manifest->update->php->path;
368
369
				if ($updatePath != '')
370
				{
371
					switch ((string) $manifest['type'])
372
					{
373
						case 'plugin':
374
							$sourcePath = JPATH_PLUGINS . '/' . (string) $manifest['group'] . '/' . $this->extensionElement;
375
							break;
376
						case 'module':
377
							if ((string) $manifest['client'] == 'administrator')
378
							{
379
								$sourcePath = JPATH_ADMINISTRATOR . '/modules/' . $this->extensionElement;
380
							}
381
							else
382
							{
383
								$sourcePath = JPATH_SITE . '/modules/' . $this->extensionElement;
384
							}
385
							break;
386
						case 'library':
387
							$sourcePath = JPATH_BASE . '/libraries/' . $this->extensionElement;
388
							break;
389
						case 'component':
390
						default:
391
							$sourcePath = JPATH_ADMINISTRATOR . '/components/' . $this->extensionElement;
392
							break;
393
					}
394
395
					if (is_dir($sourcePath . '/' . $updatePath))
396
					{
397
						$files = str_replace('.php', '', JFolder::files($sourcePath . '/' . $updatePath, '\.php$'));
398
399
						if (!empty($files))
400
						{
401
							usort($files, 'version_compare');
402
403
							if (count($files))
404
							{
405
								foreach ($files as $file)
406
								{
407
									if (version_compare($file, $this->oldVersion) > 0)
408
									{
409
										if (!$this->processPHPUpdateFile(
410
											$parent,
411
											$sourcePath . '/' . $updatePath . '/' . $file . '.php', $file, $executeAfterUpdate
412
										))
413
										{
414
											return false;
415
										}
416
									}
417
								}
418
							}
419
						}
420
					}
421
				}
422
			}
423
		}
424
425
		return true;
426
	}
427
428
	/**
429
	 * Method to process a single PHP update file
430
	 *
431
	 * @param   JInstallerAdapter  $parent              Class calling this method
432
	 * @param   string             $file                File to process
433
	 * @param   string             $version             File version
434
	 * @param   bool               $executeAfterUpdate  The name of the function to execute
435
	 *
436
	 * @return  boolean          True on success
437
	 */
438
	public function processPHPUpdateFile($parent, $file, $version, $executeAfterUpdate)
439
	{
440
		static $upgradeClasses;
441
442
		if (!isset($upgradeClasses))
443
		{
444
			$upgradeClasses = array();
445
		}
446
447
		require_once $file;
448
		$class      = ucfirst($this->extensionElement) . 'UpdateScript_' . str_replace('.', '_', str_replace('-', '_', $version));
449
		$methodName = $executeAfterUpdate ? 'executeAfterUpdate' : 'execute';
450
451
		if (class_exists($class))
452
		{
453
			if (!isset($upgradeClasses[$class]))
454
			{
455
				$upgradeClasses[$class] = new $class;
456
			}
457
458
			if (method_exists($upgradeClasses[$class], $methodName))
459
			{
460
				if (!$upgradeClasses[$class]->{$methodName}($parent))
461
				{
462
					return false;
463
				}
464
			}
465
		}
466
467
		return true;
468
	}
469
470
	/**
471
	 * Install the package libraries
472
	 *
473
	 * @param   JInstallerAdapter  $parent  class calling this method
474
	 *
475
	 * @return  void
476
	 */
477
	private function installLibraries($parent)
478
	{
479
		// Required objects
480
		$installer = $this->getInstaller();
481
		$manifest  = $this->getManifest($parent);
482
		$src       = $parent->getParent()->getPath('source');
483
484
		if ($nodes = $manifest->libraries->library)
485
		{
486
			foreach ($nodes as $node)
487
			{
488
				$extName = $node->attributes()->name;
489
				$extPath = $src . '/libraries/' . $extName;
490
				$result  = 0;
491
492
				// Standard install
493
				if (is_dir($extPath))
494
				{
495
					$result = $installer->install($extPath);
496
				}
497
				// Discover install
498
				elseif ($extId = $this->searchExtension($extName, 'library', '-1'))
499
				{
500
					$result = $installer->discover_install($extId);
501
				}
502
503
				$this->_storeStatus('libraries', array('name' => $extName, 'result' => $result));
504
			}
505
		}
506
	}
507
508
	/**
509
	 * Install the media folder
510
	 *
511
	 * @param   JInstallerAdapter  $parent  class calling this method
512
	 *
513
	 * @return  void
514
	 */
515
	private function installMedia($parent)
516
	{
517
		$installer = $this->getInstaller();
518
		$manifest  = $this->getManifest($parent);
519
		$src       = $parent->getParent()->getPath('source');
520
521
		if ($manifest && $manifest->attributes()->type == 'package')
0 ignored issues
show
introduced by
The condition $manifest->attributes()->type == 'package' is always false.
Loading history...
522
		{
523
			$installer->setPath('source', $src);
524
			$installer->parseMedia($manifest->media);
525
		}
526
	}
527
528
	/**
529
	 * Install the package modules
530
	 *
531
	 * @param   JInstallerAdapter  $parent  class calling this method
532
	 *
533
	 * @return  void
534
	 */
535
	protected function installModules($parent)
536
	{
537
		// Required objects
538
		$installer = $this->getInstaller();
539
		$manifest  = $parent->get('manifest');
540
		$src       = $parent->getParent()->getPath('source');
541
		$nodes     = $manifest->modules->module;
542
543
		if (empty($nodes))
544
		{
545
			return;
546
		}
547
548
		foreach ($nodes as $node)
549
		{
550
			$extName   = $node->attributes()->name;
551
			$extClient = $node->attributes()->client;
552
			$extPath   = $src . '/modules/' . $extClient . '/' . $extName;
553
			$result    = 0;
554
555
			// Standard install
556
			if (is_dir($extPath))
557
			{
558
				$installer->setAdapter('module');
559
				$result = $installer->install($extPath);
560
			}
561
			elseif ($extId = $this->searchExtension($extName, 'module', '-1'))
562
				// Discover install
563
			{
564
				$result = $installer->discover_install($extId);
565
			}
566
567
			$this->_storeStatus('modules', array('name' => $extName, 'client' => $extClient, 'result' => $result));
568
		}
569
	}
570
571
	/**
572
	 * Install the package libraries
573
	 *
574
	 * @param   JInstallerAdapter  $parent  class calling this method
575
	 *
576
	 * @return  void
577
	 */
578
	protected function installPlugins($parent)
579
	{
580
		// Required objects
581
		$installer = $this->getInstaller();
582
		$manifest  = $parent->get('manifest');
583
		$src       = $parent->getParent()->getPath('source');
584
		$nodes     = $manifest->plugins->plugin;
585
586
		if (empty($nodes))
587
		{
588
			return;
589
		}
590
591
		foreach ($nodes as $node)
592
		{
593
			$extName  = $node->attributes()->name;
594
			$extGroup = $node->attributes()->group;
595
			$disabled = !empty($node->attributes()->disabled) ? true : false;
596
			$extPath  = $src . '/plugins/' . $extGroup . '/' . $extName;
597
			$result   = 0;
598
599
			// Standard install
600
			if (is_dir($extPath))
601
			{
602
				$installer->setAdapter('plugin');
603
				$result = $installer->install($extPath);
604
			}
605
			elseif ($extId = $this->searchExtension($extName, 'plugin', '-1', $extGroup))
606
				// Discover install
607
			{
608
				$result = $installer->discover_install($extId);
609
			}
610
611
			// Store the result to show install summary later
612
			$this->_storeStatus('plugins', array('name' => $extName, 'group' => $extGroup, 'result' => $result));
613
614
			// Enable the installed plugin
615
			if ($result && !$disabled)
616
			{
617
				$db    = JFactory::getDBO();
618
				$query = $db->getQuery(true);
619
				$query->update($db->qn('#__extensions'));
620
				$query->set($db->qn('enabled') . ' = 1');
621
				$query->set($db->qn('state') . ' = 1');
622
				$query->where($db->qn('type') . ' = ' . $db->q('plugin'));
623
				$query->where($db->qn('element') . ' = ' . $db->q($extName));
624
				$query->where($db->qn('folder') . ' = ' . $db->q($extGroup));
625
				$db->setQuery($query)->execute();
626
			}
627
		}
628
	}
629
630
	/**
631
	 * Install the package translations
632
	 *
633
	 * @param   JInstallerAdapter  $parent  class calling this method
634
	 *
635
	 * @return  void
636
	 */
637
	protected function installTranslations($parent)
638
	{
639
		// Required objects
640
		$manifest = $parent->get('manifest');
641
642
		if (method_exists('RTranslationTable', 'batchContentElements'))
643
		{
644
			$nodes = $manifest->translations->translation;
645
646
			if (empty($nodes))
647
			{
648
				return;
649
			}
650
651
			foreach ($nodes as $node)
652
			{
653
				$extName = (string) $node->attributes()->name;
654
655
				try
656
				{
657
					RTranslationTable::batchContentElements($extName, 'install');
658
				}
659
				catch (Exception $e)
660
				{
661
					// We are already setting message queue so we don't need to set it here as well
662
				}
663
664
				$this->_storeStatus('translations', array('name' => $extName, 'result' => true));
665
			}
666
		}
667
	}
668
669
	/**
670
	 * Function to install redCORE for components
671
	 *
672
	 * @param   string             $type    type of change (install, update or discover_install)
673
	 * @param   JInstallerAdapter  $parent  class calling this method
674
	 *
675
	 * @return  void
676
	 * @throws  Exception
677
	 */
678
	protected function installRedcore($type, $parent)
679
	{
680
		// If it's installing redcore as dependency
681
		if (get_called_class() != 'Com_RedcoreInstallerScript' && $type != 'discover_install')
682
		{
683
			$manifest = $this->getManifest($parent);
684
685
			if ($manifest->redcore)
686
			{
687
				$installer              = $this->getInstaller();
688
				$redcoreFolder          = __DIR__;
689
				$redcoreComponentFolder = $this->getRedcoreComponentFolder();
690
691
				if (is_dir($redcoreFolder) && JPath::clean($redcoreFolder) != JPath::clean($redcoreComponentFolder))
692
				{
693
					$install = $this->checkComponentVersion($redcoreComponentFolder, $redcoreFolder, 'redcore.xml');
694
695
					if ($install)
696
					{
697
						$installer->install($redcoreFolder);
698
						$this->loadRedcoreLibrary();
699
					}
700
				}
701
			}
702
		}
703
		// If it is installing redCORE we want to make sure it installs redCORE library first
704
		elseif (get_called_class() == 'Com_RedcoreInstallerScript' && in_array($type, array('install', 'update', 'discover_install')))
705
		{
706
			$install = $this->checkComponentVersion(JPATH_LIBRARIES . '/redcore', __DIR__ . '/libraries/redcore', 'redcore.xml');
707
708
			// Only install if installation in the package is newer version
709
			if ($install)
710
			{
711
				$this->installLibraries($parent);
712
			}
713
		}
714
	}
715
716
	/**
717
	 * Function to install redCORE for components
718
	 *
719
	 * @param   JInstallerAdapter  $parent  class calling this method
720
	 *
721
	 * @return  void
722
	 */
723
	protected function postInstallRedcore($parent)
724
	{
725
		$manifest = $this->getManifest($parent);
726
		$type     = $manifest->attributes()->type;
727
728
		if ($type == 'component')
0 ignored issues
show
introduced by
The condition $type == 'component' is always false.
Loading history...
729
		{
730
			$redcoreNode = $manifest->redcore;
731
732
			if ($redcoreNode)
733
			{
734
				$redcoreFolder = __DIR__;
735
736
				if (!empty($redcoreFolder))
737
				{
738
					$version = $redcoreNode->attributes()->version;
739
740
					$class  = get_called_class();
741
					$option = strtolower(strstr($class, 'Installer', true));
742
743
					$db    = JFactory::getDBO();
744
					$query = $db->getQuery(true)
745
						->select($db->qn('params'))
746
						->from($db->qn('#__extensions'))
747
						->where($db->qn('type') . ' = ' . $db->q($type))
748
						->where($db->qn('element') . ' = ' . $db->q($option));
749
750
					$comParams = new Registry($db->setQuery($query)->loadResult());
751
					$comParams->set('redcore',
752
						array('version' => (string) $version)
753
					);
754
755
					$query = $db->getQuery(true);
756
					$query->update($db->qn('#__extensions'));
757
					$query->set($db->qn('params') . ' = ' . $db->q($comParams->toString()));
758
					$query->where($db->qn('type') . ' = ' . $db->q($type));
759
					$query->where($db->qn('element') . ' = ' . $db->q($option));
760
					$db->setQuery($query)->execute();
761
				}
762
			}
763
		}
764
	}
765
766
	/**
767
	 * Install the package templates
768
	 *
769
	 * @param   JInstallerAdapter  $parent  class calling this method
770
	 *
771
	 * @return  void
772
	 */
773
	private function installTemplates($parent)
774
	{
775
		// Required objects
776
		$installer = $this->getInstaller();
777
		$manifest  = $parent->get('manifest');
778
		$src       = $parent->getParent()->getPath('source');
779
		$nodes     = $manifest->templates->template;
780
781
		if ($nodes)
782
		{
783
			foreach ($nodes as $node)
784
			{
785
				$extName   = $node->attributes()->name;
786
				$extClient = $node->attributes()->client;
787
				$extPath   = $src . '/templates/' . $extClient . '/' . $extName;
788
				$result    = 0;
789
790
				// Standard install
791
				if (is_dir($extPath))
792
				{
793
					$installer->setAdapter('template');
794
					$result = $installer->install($extPath);
795
				}
796
				// Discover install
797
				elseif ($extId = $this->searchExtension($extName, 'template', '-1'))
798
				{
799
					$result = $installer->discover_install($extId);
800
				}
801
802
				$this->_storeStatus('templates', array('name' => $extName, 'client' => $extClient, 'result' => $result));
803
			}
804
		}
805
	}
806
807
	/**
808
	 * Install the package Cli scripts
809
	 *
810
	 * @param   JInstallerAdapter  $parent  class calling this method
811
	 *
812
	 * @return  void
813
	 */
814
	private function installCli($parent)
815
	{
816
		// Required objects
817
		$installer = $this->getInstaller();
818
		$manifest  = $parent->get('manifest');
819
		$src       = $parent->getParent()->getPath('source');
820
821
		if (!$manifest)
822
		{
823
			return;
824
		}
825
826
		$installer->setPath('source', $src);
827
		$element = $manifest->cli;
828
829
		if (!$element || !count($element->children()))
830
		{
831
			// Either the tag does not exist or has no children therefore we return zero files processed.
832
			return;
833
		}
834
835
		$nodes = $element->children();
836
837
		foreach ($nodes as $node)
838
		{
839
			// Here we set the folder name we are going to copy the files to.
840
			$name = (string) $node->attributes()->name;
841
842
			// Here we set the folder we are going to copy the files to.
843
			$destination = JPath::clean(JPATH_ROOT . '/cli/' . $name);
844
845
			// Here we set the folder we are going to copy the files from.
846
			$folder = (string) $node->attributes()->folder;
847
848
			if ($folder && file_exists($src . '/' . $folder))
849
			{
850
				$source = $src . '/' . $folder;
851
			}
852
			else
853
			{
854
				// Cli folder does not exist
855
				continue;
856
			}
857
858
			$copyFiles = $this->prepareFilesForCopy($element, $source, $destination);
859
860
			$installer->copyFiles($copyFiles, true);
861
		}
862
	}
863
864
	/**
865
	 * Method to parse through a webservices element of the installation manifest and take appropriate
866
	 * action.
867
	 *
868
	 * @param   JInstallerAdapter  $parent  class calling this method
869
	 *
870
	 * @return  boolean     True on success
871
	 *
872
	 * @since   1.3
873
	 */
874
	public function installWebservices($parent)
875
	{
876
		$installer = $this->getInstaller();
877
		$manifest  = $this->getManifest($parent);
878
		$src       = $parent->getParent()->getPath('source');
879
880
		if (!$manifest)
0 ignored issues
show
introduced by
$manifest is of type SimpleXMLElement, thus it always evaluated to true.
Loading history...
881
		{
882
			return false;
883
		}
884
885
		$installer->setPath('source', $src);
886
		$element = $manifest->webservices;
887
888
		if (!$element || !count($element->children()))
0 ignored issues
show
introduced by
$element is of type SimpleXMLElement, thus it always evaluated to true.
Loading history...
889
		{
890
			// Either the tag does not exist or has no children therefore we return zero files processed.
891
			return false;
892
		}
893
894
		// Here we set the folder we are going to copy the files from.
895
		$folder = (string) $element->attributes()->folder;
896
897
		// This prevents trying to install webservice from other extension directory if webservice folder is not set
898
		if (!$folder || !is_dir($src . '/' . $folder))
899
		{
900
			return false;
901
		}
902
903
		// Here we set the folder we are going to copy the files to.
904
		$destination = JPath::clean(RApiHalHelper::getWebservicesPath());
905
		$source      = $src . '/' . $folder;
906
907
		$copyFiles = $this->prepareFilesForCopy($element, $source, $destination);
908
909
		// Copy the webservice XML files
910
		$return = $installer->copyFiles($copyFiles, true);
911
912
		// Recreate or create new SOAP WSDL files
913
		if (method_exists('RApiSoapHelper', 'generateWsdlFromFolder'))
914
		{
915
			foreach ($element->children() as $file)
916
			{
917
				RApiSoapHelper::generateWsdlFromFolder($destination . '/' . $file);
918
			}
919
		}
920
921
		return $return;
922
	}
923
924
	/**
925
	 * Method to parse through a xml element of the installation manifest and take appropriate action.
926
	 *
927
	 * @param   SimpleXMLElement  $element      Element to iterate
928
	 * @param   string            $source       Source location of the files
929
	 * @param   string            $destination  Destination location of the files
930
	 *
931
	 * @return  array
932
	 *
933
	 * @since   1.4
934
	 */
935
	public function prepareFilesForCopy($element, $source, $destination)
936
	{
937
		$copyFiles = array();
938
939
		// Process each file in the $files array (children of $tagName).
940
		foreach ($element->children() as $file)
941
		{
942
			$path         = array();
943
			$path['src']  = $source . '/' . $file;
944
			$path['dest'] = $destination . '/' . $file;
945
946
			// Is this path a file or folder?
947
			$path['type'] = ($file->getName() == 'folder') ? 'folder' : 'file';
948
949
			if (basename($path['dest']) != $path['dest'])
950
			{
951
				$newDir = dirname($path['dest']);
952
953
				if (!JFolder::create($newDir))
954
				{
955
					JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_CREATE_DIRECTORY', $newDir), JLog::WARNING, 'jerror');
956
957
					return array();
958
				}
959
			}
960
961
			// Add the file to the copyfiles array
962
			$copyFiles[] = $path;
963
		}
964
965
		return $copyFiles;
966
	}
967
968
	/**
969
	 * Method to run after an install/update/uninstall method
970
	 *
971
	 * @param   object             $type    type of change (install, update or discover_install)
972
	 * @param   JInstallerAdapter  $parent  class calling this method
973
	 *
974
	 * @return  boolean
975
	 */
976
	public function postflight($type, $parent)
977
	{
978
		$installer = get_called_class();
979
980
		// If it's installing redcore as dependency
981
		if ($installer !== 'Com_RedcoreInstallerScript' && $type != 'discover_install')
982
		{
983
			$this->postInstallRedcore($parent);
984
		}
985
986
		// Execute the postflight tasks from the manifest
987
		$this->postFlightFromManifest($type, $parent);
988
989
		$this->installTranslations($parent);
990
991
		/** @var JXMLElement $manifest */
992
		$manifest = $parent->get('manifest');
993
994
		if (in_array($type, array('install', 'update', 'discover_install')))
995
		{
996
			$attributes = current($manifest->attributes());
0 ignored issues
show
Bug introduced by
$manifest->attributes() of type SimpleXMLElement is incompatible with the type array expected by parameter $array of current(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

996
			$attributes = current(/** @scrutinizer ignore-type */ $manifest->attributes());
Loading history...
997
998
			// If it's a component
999
			if (isset($attributes['type']) && (string) $attributes['type'] === 'component')
1000
			{
1001
				$this->loadRedcoreLanguage();
1002
				$this->displayComponentInfo($parent);
1003
			}
1004
		}
1005
1006
		if ($type == 'update')
0 ignored issues
show
introduced by
The condition $type == 'update' is always false.
Loading history...
1007
		{
1008
			$db = JFactory::getDbo();
1009
			$db->setQuery('TRUNCATE ' . $db->qn('#__redcore_schemas'))
1010
				->execute();
1011
		}
1012
1013
		// If this is install redcore component.
1014
		if ($installer == 'Com_RedcoreInstallerScript')
1015
		{
1016
			$this->insertSiteDomain();
1017
		}
1018
1019
		return true;
1020
	}
1021
1022
	/**
1023
	 * Execute the postflight tasks from the manifest if there is any.
1024
	 *
1025
	 * @param   object             $type    type of change (install, update or discover_install)
1026
	 * @param   JInstallerAdapter  $parent  class calling this method
1027
	 *
1028
	 * @return  void
1029
	 */
1030
	protected function postFlightFromManifest($type, $parent)
1031
	{
1032
		$manifest = $parent->get('manifest');
1033
1034
		if ($tasks = $manifest->postflight->task)
1035
		{
1036
			/** @var JXMLElement $task */
1037
			foreach ($tasks as $task)
1038
			{
1039
				$attributes = current($task->attributes());
1040
1041
				// No task name
1042
				if (!isset($attributes['name']))
1043
				{
1044
					continue;
1045
				}
1046
1047
				$taskName = $attributes['name'];
1048
				$class    = get_called_class();
1049
1050
				// Do we have some parameters ?
1051
				$parameters = array();
1052
1053
				if ($params = $task->parameter)
1054
				{
1055
					foreach ($params as $param)
1056
					{
1057
						$parameters[] = (string) $param;
1058
					}
1059
				}
1060
1061
				$parameters = array_merge(array($type, $parent), $parameters);
1062
1063
				// Call the task with $type and $parent as parameters
1064
				if (method_exists($class, $taskName))
1065
				{
1066
					call_user_func_array(array($class, $taskName), $parameters);
1067
				}
1068
			}
1069
		}
1070
	}
1071
1072
	/**
1073
	 * Delete the menu item of the extension.
1074
	 *
1075
	 * @param   string             $type    Type of change (install, update or discover_install)
1076
	 * @param   JInstallerAdapter  $parent  Class calling this method
1077
	 * @param   string             $client  The client
1078
	 *
1079
	 * @return  void
1080
	 */
1081
	protected function deleteMenu($type, $parent, $client = null)
1082
	{
1083
		/** @var JXMLElement $manifest */
1084
		$manifest   = $parent->get('manifest');
1085
		$attributes = current($manifest->attributes());
0 ignored issues
show
Bug introduced by
$manifest->attributes() of type SimpleXMLElement is incompatible with the type array expected by parameter $array of current(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1085
		$attributes = current(/** @scrutinizer ignore-type */ $manifest->attributes());
Loading history...
1086
1087
		// If it's not a component
1088
		if (!isset($attributes['type']))
1089
		{
1090
			return;
1091
		}
1092
1093
		$type          = $attributes['type'];
1094
		$componentName = (string) $manifest->name;
1095
1096
		if (empty($componentName))
1097
		{
1098
			return;
1099
		}
1100
1101
		$db    = JFactory::getDbo();
1102
		$query = $db->getQuery(true)
1103
			->delete('#__menu')
1104
			->where('type = ' . $db->q($type));
1105
1106
		if (!empty($client))
1107
		{
1108
			$query->where($db->qn('client_id') . ' = ' . $db->q($client));
1109
		}
1110
1111
		$query->where(
1112
			array(
1113
				'title = ' . $db->q($componentName),
1114
				'title = ' . $db->q(strtolower($componentName))
1115
			),
1116
			'OR'
1117
		);
1118
1119
		$db->setQuery($query);
1120
		$db->execute();
1121
	}
1122
1123
	/**
1124
	 * Search a extension in the database
1125
	 *
1126
	 * @param   string  $element  Extension technical name/alias
1127
	 * @param   string  $type     Type of extension (component, file, language, library, module, plugin)
1128
	 * @param   string  $state    State of the searched extension
1129
	 * @param   string  $folder   Folder name used mainly in plugins
1130
	 *
1131
	 * @return  integer           Extension identifier
1132
	 */
1133
	protected function searchExtension($element, $type, $state = null, $folder = null)
1134
	{
1135
		$db    = JFactory::getDBO();
1136
		$query = $db->getQuery(true)
1137
			->select($db->qn('extension_id'))
1138
			->from($db->qn("#__extensions"))
1139
			->where($db->qn('type') . ' = ' . $db->q($type))
1140
			->where($db->qn('element') . ' = ' . $db->q($element));
1141
1142
		if (null !== $state)
1143
		{
1144
			$query->where($db->qn('state') . ' = ' . (int) $state);
1145
		}
1146
1147
		if (null !== $folder)
1148
		{
1149
			$query->where($db->qn('folder') . ' = ' . $db->q($folder));
1150
		}
1151
1152
		return $db->setQuery($query)->loadResult();
1153
	}
1154
1155
	/**
1156
	 * method to update the component
1157
	 *
1158
	 * @param   JInstallerAdapter  $parent  class calling this method
1159
	 *
1160
	 * @return void
1161
	 */
1162
	public function update($parent)
1163
	{
1164
		// Process PHP update files
1165
		$this->phpUpdates($parent, false);
1166
1167
		// Common tasks for install or update
1168
		$this->installOrUpdate($parent);
1169
1170
		// Process PHP update files
1171
		$this->phpUpdates($parent, true);
1172
	}
1173
1174
	/**
1175
	 * Prevents uninstalling redcore component if some components using it are still installed.
1176
	 *
1177
	 * @param   JInstallerAdapter  $parent  class calling this method
1178
	 *
1179
	 * @return  void
1180
	 *
1181
	 * @throws  Exception
1182
	 */
1183
	private function preventUninstallRedcore($parent)
1184
	{
1185
		$this->loadRedcoreLibrary();
1186
1187
		// Avoid uninstalling redcore if there is a component using it
1188
		$manifest  = $this->getManifest($parent);
1189
		$isRedcore = 'COM_REDCORE' == (string) $manifest->name;
1190
1191
		if ($isRedcore)
1192
		{
1193
			if (method_exists('RComponentHelper', 'getRedcoreComponents'))
1194
			{
1195
				$components = RComponentHelper::getRedcoreComponents();
1196
1197
				if (!empty($components))
1198
				{
1199
					$app     = JFactory::getApplication();
1200
					$message = sprintf(
1201
						'Cannot uninstall redCORE because the following components are using it: <br /> [%s]',
1202
						implode(',<br /> ', $components)
1203
					);
1204
1205
					$app->enqueueMessage($message, 'error');
1206
					$app->redirect('index.php?option=com_installer&view=manage');
1207
				}
1208
			}
1209
		}
1210
	}
1211
1212
	/**
1213
	 * method to uninstall the component
1214
	 *
1215
	 * @param   JInstallerAdapter  $parent  class calling this method
1216
	 *
1217
	 * @return  void
1218
	 *
1219
	 * @throws  Exception
1220
	 */
1221
	public function uninstall($parent)
1222
	{
1223
		$this->preventUninstallRedcore($parent);
1224
1225
		// Uninstall extensions
1226
		$this->uninstallTranslations($parent);
1227
		$this->uninstallMedia($parent);
1228
		$this->uninstallWebservices($parent);
1229
		$this->uninstallModules($parent);
1230
		$this->uninstallPlugins($parent);
1231
		$this->uninstallTemplates($parent);
1232
		$this->uninstallCli($parent);
1233
		$this->uninstallLibraries($parent);
1234
	}
1235
1236
	/**
1237
	 * Uninstall all Translation tables from database
1238
	 *
1239
	 * @param   JInstallerAdapter  $parent  class calling this method
1240
	 *
1241
	 * @return  void
1242
	 *
1243
	 * @throws  Exception
1244
	 */
1245
	protected function uninstallTranslations($parent)
1246
	{
1247
		if (method_exists('RTranslationTable', 'batchContentElements'))
1248
		{
1249
			// Required objects
1250
			$manifest              = $parent->get('manifest');
1251
			$class                 = get_called_class();
1252
			$deleteIds             = array();
1253
			$translationTables     = RTranslationTable::getInstalledTranslationTables(true);
1254
			$translationTableModel = RModel::getAdminInstance('Translation_Table', array(), 'com_redcore');
1255
1256
			// Delete specific extension translation tables
1257
			if ($class != 'Com_RedcoreInstallerScript')
1258
			{
1259
				$nodes = $manifest->translations->translation;
1260
1261
				if ($nodes)
1262
				{
1263
					foreach ($nodes as $node)
1264
					{
1265
						$extensionOption = (string) $node->attributes()->name;
1266
1267
						if (!empty($translationTables))
1268
						{
1269
							foreach ($translationTables as $translationTableParams)
1270
							{
1271
								if ($extensionOption == $translationTableParams->option)
1272
								{
1273
									$deleteIds[] = $translationTableParams->id;
1274
								}
1275
							}
1276
						}
1277
					}
1278
				}
1279
			}
1280
			// We delete everything
1281
			else
1282
			{
1283
				if (!empty($translationTables))
1284
				{
1285
					foreach ($translationTables as $translationTableParams)
1286
					{
1287
						$deleteIds[] = $translationTableParams->id;
1288
					}
1289
				}
1290
			}
1291
1292
			if (!empty($deleteIds))
1293
			{
1294
				foreach ($deleteIds as $deleteId)
1295
				{
1296
					try
1297
					{
1298
						$translationTableModel->delete($deleteId);
0 ignored issues
show
Bug introduced by
The method delete() does not exist on RModel. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1298
						$translationTableModel->/** @scrutinizer ignore-call */ 
1299
                              delete($deleteId);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1299
					}
1300
					catch (Exception $e)
1301
					{
1302
						JFactory::getApplication()->enqueueMessage(
1303
							JText::sprintf('LIB_REDCORE_TRANSLATIONS_DELETE_ERROR', $e->getMessage()), 'error'
1304
						);
1305
					}
1306
				}
1307
			}
1308
		}
1309
	}
1310
1311
	/**
1312
	 * Uninstall the package libraries
1313
	 *
1314
	 * @param   JInstallerAdapter  $parent  class calling this method
1315
	 *
1316
	 * @return  void
1317
	 */
1318
	protected function uninstallLibraries($parent)
1319
	{
1320
		// Required objects
1321
		$installer = $this->getInstaller();
1322
		$manifest  = $this->getManifest($parent);
1323
		$nodes     = $manifest->libraries->library;
1324
1325
		if ($nodes)
0 ignored issues
show
introduced by
$nodes is of type SimpleXMLElement, thus it always evaluated to true.
Loading history...
1326
		{
1327
			foreach ($nodes as $node)
1328
			{
1329
				$extName = $node->attributes()->name;
1330
				$result  = 0;
1331
				$extId   = $this->searchExtension($extName, 'library');
1332
1333
				if ($extId)
1334
				{
1335
					$result = $installer->uninstall('library', $extId);
1336
				}
1337
1338
				// Store the result to show install summary later
1339
				$this->_storeStatus('libraries', array('name' => $extName, 'result' => $result));
1340
			}
1341
		}
1342
	}
1343
1344
	/**
1345
	 * Uninstall the media folder
1346
	 *
1347
	 * @param   JInstallerAdapter  $parent  class calling this method
1348
	 *
1349
	 * @return  void
1350
	 */
1351
	protected function uninstallMedia($parent)
1352
	{
1353
		// Required objects
1354
		$installer = $this->getInstaller();
1355
		$manifest  = $this->getManifest($parent);
1356
1357
		if ($manifest && $manifest->attributes()->type == 'package')
0 ignored issues
show
introduced by
The condition $manifest->attributes()->type == 'package' is always false.
Loading history...
1358
		{
1359
			$installer->removeFiles($manifest->media);
1360
		}
1361
	}
1362
1363
	/**
1364
	 * Uninstall the webservices
1365
	 *
1366
	 * @param   JInstallerAdapter  $parent  class calling this method
1367
	 *
1368
	 * @return  boolean
1369
	 */
1370
	protected function uninstallWebservices($parent)
1371
	{
1372
		// Required objects
1373
		$manifest = $this->getManifest($parent);
1374
1375
		if (!$manifest)
0 ignored issues
show
introduced by
$manifest is of type SimpleXMLElement, thus it always evaluated to true.
Loading history...
1376
		{
1377
			return false;
1378
		}
1379
1380
		// We will use webservices removal function to remove webservice files
1381
		$element = $manifest->webservices;
1382
1383
		if (!$element || !count($element->children()))
0 ignored issues
show
introduced by
$element is of type SimpleXMLElement, thus it always evaluated to true.
Loading history...
1384
		{
1385
			// Either the tag does not exist or has no children therefore we return zero files processed.
1386
			return true;
1387
		}
1388
1389
		$returnValue = true;
1390
1391
		// Get the array of file nodes to process
1392
		$files  = $element->children();
1393
		$source = RApiHalHelper::getWebservicesPath();
1394
1395
		// Process each file in the $files array (children of $tagName).
1396
		foreach ($files as $file)
1397
		{
1398
			$path = $source . '/' . $file;
1399
1400
			// Actually delete the files/folders
1401
1402
			if (is_dir($path))
1403
			{
1404
				$val = JFolder::delete($path);
1405
			}
1406
			else
1407
			{
1408
				$val = JFile::delete($path);
1409
			}
1410
1411
			if ($val === false)
1412
			{
1413
				JLog::add(JText::sprintf('LIB_REDCORE_INSTALLER_ERROR_FAILED_TO_DELETE', $path), JLog::WARNING, 'jerror');
1414
				$returnValue = false;
1415
			}
1416
		}
1417
1418
		return $returnValue;
1419
	}
1420
1421
	/**
1422
	 * Uninstall the Cli
1423
	 *
1424
	 * @param   JInstallerAdapter  $parent  class calling this method
1425
	 *
1426
	 * @return  boolean
1427
	 */
1428
	protected function uninstallCli($parent)
1429
	{
1430
		// Required objects
1431
		$manifest = $this->getManifest($parent);
1432
1433
		if (!$manifest)
0 ignored issues
show
introduced by
$manifest is of type SimpleXMLElement, thus it always evaluated to true.
Loading history...
1434
		{
1435
			return false;
1436
		}
1437
1438
		// We will use cli removal function to remove cli folders
1439
		$element = $manifest->cli;
1440
1441
		if (!$element || !count($element->children()))
0 ignored issues
show
introduced by
$element is of type SimpleXMLElement, thus it always evaluated to true.
Loading history...
1442
		{
1443
			// Either the tag does not exist or has no children therefore we return zero files processed.
1444
			return true;
1445
		}
1446
1447
		$returnValue = true;
1448
1449
		// Get the array of file nodes to process
1450
		$folders = $element->children();
1451
		$source  = JPATH_ROOT . '/cli/';
1452
1453
		// Process each folder in the $folders array
1454
		foreach ($folders as $folder)
1455
		{
1456
			// Here we set the folder name we are going to delete from cli main folder
1457
			$name = (string) $folder->attributes()->name;
1458
1459
			// If name is not set we should not delete whole cli folder
1460
			if (empty($name))
1461
			{
1462
				continue;
1463
			}
1464
1465
			$path = $source . '/' . $name;
1466
1467
			// Delete the files/folders
1468
			if (is_dir($path))
1469
			{
1470
				$val = JFolder::delete($path);
1471
			}
1472
			else
1473
			{
1474
				$val = JFile::delete($path);
1475
			}
1476
1477
			if ($val === false)
1478
			{
1479
				JLog::add(JText::sprintf('LIB_REDCORE_INSTALLER_ERROR_FAILED_TO_DELETE', $path), JLog::WARNING, 'jerror');
1480
				$returnValue = false;
1481
			}
1482
		}
1483
1484
		return $returnValue;
1485
	}
1486
1487
	/**
1488
	 * Uninstall the package modules
1489
	 *
1490
	 * @param   JInstallerAdapter  $parent  class calling this method
1491
	 *
1492
	 * @return  void
1493
	 */
1494
	protected function uninstallModules($parent)
1495
	{
1496
		// Required objects
1497
		$installer = $this->getInstaller();
1498
		$manifest  = $this->getManifest($parent);
1499
		$nodes     = $manifest->modules->module;
1500
1501
		if (empty($nodes))
1502
		{
1503
			return;
1504
		}
1505
1506
		foreach ($nodes as $node)
1507
		{
1508
			$extName   = $node->attributes()->name;
1509
			$extClient = $node->attributes()->client;
1510
			$result    = 0;
1511
			$extId     = $this->searchExtension($extName, 'module');
1512
1513
			if ($extId)
1514
			{
1515
				$result = $installer->uninstall('module', $extId);
1516
			}
1517
1518
			// Store the result to show install summary later
1519
			$this->_storeStatus('modules', array('name' => $extName, 'client' => $extClient, 'result' => $result));
1520
		}
1521
	}
1522
1523
	/**
1524
	 * Uninstall the package plugins
1525
	 *
1526
	 * @param   JInstallerAdapter  $parent  class calling this method
1527
	 *
1528
	 * @return  void
1529
	 */
1530
	protected function uninstallPlugins($parent)
1531
	{
1532
		// Required objects
1533
		$installer = $this->getInstaller();
1534
		$manifest  = $this->getManifest($parent);
1535
		$nodes     = $manifest->plugins->plugin;
1536
1537
		if (empty($nodes))
1538
		{
1539
			return;
1540
		}
1541
1542
		foreach ($nodes as $node)
1543
		{
1544
			$extName  = $node->attributes()->name;
1545
			$extGroup = $node->attributes()->group;
1546
			$result   = 0;
1547
			$extId    = $this->searchExtension($extName, 'plugin', null, $extGroup);
1548
1549
			if ($extId)
1550
			{
1551
				$result = $installer->uninstall('plugin', $extId);
1552
			}
1553
1554
			// Store the result to show install summary later
1555
			$this->_storeStatus('plugins', array('name' => $extName, 'group' => $extGroup, 'result' => $result));
1556
		}
1557
	}
1558
1559
	/**
1560
	 * Uninstall the package templates
1561
	 *
1562
	 * @param   JInstallerAdapter  $parent  class calling this method
1563
	 *
1564
	 * @return  void
1565
	 */
1566
	protected function uninstallTemplates($parent)
1567
	{
1568
		// Required objects
1569
		$installer = $this->getInstaller();
1570
		$manifest  = $this->getManifest($parent);
1571
		$nodes     = $manifest->templates->template;
1572
1573
		if (empty($nodes))
1574
		{
1575
			return;
1576
		}
1577
1578
		foreach ($nodes as $node)
1579
		{
1580
			$extName   = $node->attributes()->name;
1581
			$extClient = $node->attributes()->client;
1582
			$result    = 0;
1583
			$extId     = $this->searchExtension($extName, 'template', 0);
1584
1585
			if ($extId)
1586
			{
1587
				$result = $installer->uninstall('template', $extId);
1588
			}
1589
1590
			// Store the result to show install summary later
1591
			$this->_storeStatus('templates', array('name' => $extName, 'client' => $extClient, 'result' => $result));
1592
		}
1593
	}
1594
1595
	/**
1596
	 * Store the result of trying to install an extension
1597
	 *
1598
	 * @param   string  $type    Type of extension (libraries, modules, plugins)
1599
	 * @param   array   $status  The status info
1600
	 *
1601
	 * @return void
1602
	 */
1603
	private function _storeStatus($type, $status)
1604
	{
1605
		// Initialise status object if needed
1606
		if (null === $this->status)
1607
		{
1608
			$this->status = new stdClass;
1609
		}
1610
1611
		// Initialise current status type if needed
1612
		if (!isset($this->status->{$type}))
1613
		{
1614
			$this->status->{$type} = array();
1615
		}
1616
1617
		// Insert the status
1618
		$this->status->{$type}[] = $status;
1619
	}
1620
1621
	/**
1622
	 * Method to display component info
1623
	 *
1624
	 * @param   JInstallerAdapter  $parent   Class calling this method
1625
	 * @param   string             $message  Message to apply to the Component info layout
1626
	 *
1627
	 * @return  void
1628
	 */
1629
	public function displayComponentInfo($parent, $message = '')
1630
	{
1631
		$this->loadRedcoreLibrary();
1632
1633
		if ($this->showComponentInfo && method_exists('RComponentHelper', 'displayComponentInfo'))
1634
		{
1635
			$manifest = $this->getManifest($parent);
1636
			echo RComponentHelper::displayComponentInfo((string) $manifest->name, $message);
1637
		}
1638
	}
1639
1640
	/**
1641
	 * Load redCORE component language file
1642
	 *
1643
	 * @param   string  $path  Path to the language folder
1644
	 *
1645
	 * @return  void
1646
	 */
1647
	public function loadRedcoreLanguage($path = JPATH_ADMINISTRATOR)
1648
	{
1649
		// Load common and local language files.
1650
		$lang = JFactory::getLanguage();
1651
1652
		// Load language file
1653
		$lang->load('com_redcore', $path, null, true, true)
1654
		|| $lang->load('com_redcore', $path . '/components/com_redcore', null, true, true)
1655
		|| $lang->load('com_redcore', $path . '/components/com_redcore/admin', null, true, true);
1656
	}
1657
1658
	/**
1659
	 * Load redCORE library
1660
	 *
1661
	 * @return  void
1662
	 */
1663
	public function loadRedcoreLibrary()
1664
	{
1665
		$redcoreLoader = JPATH_LIBRARIES . '/redcore/bootstrap.php';
1666
1667
		if (file_exists($redcoreLoader))
1668
		{
1669
			require_once $redcoreLoader;
1670
1671
			RBootstrap::bootstrap(false);
1672
		}
1673
	}
1674
1675
	/**
1676
	 * Checks version of the extension and returns
1677
	 *
1678
	 * @param   string  $original  Original path
1679
	 * @param   string  $source    Install path
1680
	 * @param   string  $xmlFile   Component filename
1681
	 *
1682
	 * @return  boolean  Returns true if current version is lower or equal or if that extension do not exist
1683
	 * @throws  Exception
1684
	 */
1685
	public function checkComponentVersion($original, $source, $xmlFile)
1686
	{
1687
		if (is_dir($original))
1688
		{
1689
			try
1690
			{
1691
				$source      = $source . '/' . $xmlFile;
1692
				$sourceXml   = new SimpleXMLElement($source, 0, true);
1693
				$original    = $original . '/' . $xmlFile;
1694
				$originalXml = new SimpleXMLElement($original, 0, true);
1695
1696
				if (version_compare((string) $sourceXml->version, (string) $originalXml->version, '<'))
1697
				{
1698
					return false;
1699
				}
1700
			}
1701
			catch (Exception $e)
1702
			{
1703
				JFactory::getApplication()->enqueueMessage(
1704
					JText::_('COM_REDCORE_INSTALL_UNABLE_TO_CHECK_VERSION'),
1705
					'message'
1706
				);
1707
			}
1708
		}
1709
1710
		return true;
1711
	}
1712
1713
	/**
1714
	 * Gets or generates the element name (using the manifest)
1715
	 *
1716
	 * @param   JInstallerAdapter  $parent    Parent adapter
1717
	 * @param   SimpleXMLElement   $manifest  Extension manifest
1718
	 *
1719
	 * @return  string  Element
1720
	 */
1721
	public function getElement($parent, $manifest = null)
1722
	{
1723
		if (method_exists($parent, 'getElement'))
1724
		{
1725
			return $parent->getElement();
1726
		}
1727
1728
		if (null === $manifest)
1729
		{
1730
			$manifest = $parent->get('manifest');
1731
		}
1732
1733
		if (isset($manifest->element))
1734
		{
1735
			$element = (string) $manifest->element;
1736
		}
1737
		else
1738
		{
1739
			$element = (string) $manifest->name;
1740
		}
1741
1742
		// Filter the name for illegal characters
1743
		return strtolower(JFilterInput::getInstance()->clean($element, 'cmd'));
1744
	}
1745
1746
	/**
1747
	 * Gets the path of redCORE component
1748
	 *
1749
	 * @return  string
1750
	 */
1751
	public function getRedcoreComponentFolder()
1752
	{
1753
		return JPATH_ADMINISTRATOR . '/components/com_redcore';
1754
	}
1755
1756
	/**
1757
	 * Shit happens. Patched function to bypass bug in package uninstaller
1758
	 *
1759
	 * @param   JInstallerAdapter  $parent  Parent object
1760
	 *
1761
	 * @return  void
1762
	 */
1763
	protected function loadManifest($parent)
1764
	{
1765
		$element      = strtolower(str_replace('InstallerScript', '', get_called_class()));
1766
		$elementParts = explode('_', $element);
1767
1768
		// Type not properly detected or not a package
1769
		if (count($elementParts) !== 2 || strtolower($elementParts[0]) !== 'pkg')
1770
		{
1771
			$this->manifest = $parent->get('manifest');
1772
1773
			return;
1774
		}
1775
1776
		$rootPath     = $parent->getParent()->getPath('extension_root');
1777
		$manifestPath = dirname($rootPath);
1778
		$manifestFile = $manifestPath . '/' . $element . '.xml';
1779
1780
		// Package manifest found
1781
		if (file_exists($manifestFile))
1782
		{
1783
			$this->manifest = new SimpleXMLElement($manifestFile);
1784
1785
			return;
1786
		}
1787
1788
		$this->manifest = $parent->get('manifest');
1789
	}
1790
1791
	/**
1792
	 * Setup site url for redCORE config
1793
	 *
1794
	 * @return  void
1795
	 */
1796
	private function insertSiteDomain()
1797
	{
1798
		$db    = JFactory::getDbo();
1799
		$query = $db->getQuery(true)
1800
			->select($db->qn('extension_id'))
1801
			->from($db->qn('#__extensions'))
1802
			->where($db->qn('type') . ' = ' . $db->q('component'))
1803
			->where($db->qn('element') . ' = ' . $db->q('com_redcore'));
1804
1805
		$extensionId = $db->setQuery($query)->loadResult();
1806
1807
		if (!$extensionId)
1808
		{
1809
			return;
1810
		}
1811
1812
		/** @var JTableExtension $table */
1813
		$table = JTable::getInstance('Extension', 'JTable');
1814
1815
		if (!$table->load($extensionId))
1816
		{
1817
			return;
1818
		}
1819
1820
		$params = new Registry($table->get('params'));
1821
1822
		// Skip update if already exist
1823
		if ($params->get('domain', ''))
1824
		{
1825
			return;
1826
		}
1827
1828
		$params->set('domain', $_SERVER['SERVER_NAME']);
1829
		$table->set('params', $params->toString());
1830
		$table->store();
1831
	}
1832
}
1833