GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

LocaliseHelper::getReleases()   F
last analyzed

Complexity

Conditions 18
Paths 726

Size

Total Lines 114

Duplication

Lines 68
Ratio 59.65 %

Importance

Changes 0
Metric Value
cc 18
nc 726
nop 0
dl 68
loc 114
rs 0.8644
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @package     Com_Localise
4
 * @subpackage  helper
5
 *
6
 * @copyright   Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
7
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
8
 */
9
10
defined('_JEXEC') or die;
11
12
use Joomla\Github\Github;
13
14
jimport('joomla.filesystem.folder');
15
jimport('joomla.filesystem.path');
16
jimport("joomla.utilities.date");
17
18
/**
19
 * Localise Helper class
20
 *
21
 * @package     Extensions.Components
22
 * @subpackage  Localise
23
 * @since       4.0
24
 */
25
abstract class LocaliseHelper
26
{
27
	/**
28
	 * Array containing the origin information
29
	 *
30
	 * @var    array
31
	 * @since  4.0
32
	 */
33
	protected static $origins = array('site' => null, 'administrator' => null, 'installation' => null);
34
35
	/**
36
	 * Array containing the package information
37
	 *
38
	 * @var    array
39
	 * @since  4.0
40
	 */
41
	protected static $packages = array();
42
43
	/**
44
	 * Prepares the component submenu
45
	 *
46
	 * @param   string  $vName  Name of the active view
47
	 *
48
	 * @return  void
49
	 *
50
	 * @since   4.0
51
	 */
52
	public static function addSubmenu($vName)
53
	{
54
		JHtmlSidebar::addEntry(
55
			JText::_('COM_LOCALISE_SUBMENU_LANGUAGES'),
56
			'index.php?option=com_localise&view=languages',
57
			$vName == 'languages'
58
		);
59
60
		JHtmlSidebar::addEntry(
61
			JText::_('COM_LOCALISE_SUBMENU_TRANSLATIONS'),
62
			'index.php?option=com_localise&view=translations',
63
			$vName == 'translations'
64
		);
65
66
		JHtmlSidebar::addEntry(
67
			JText::_('COM_LOCALISE_SUBMENU_PACKAGES'),
68
			'index.php?option=com_localise&view=packages',
69
			$vName == 'packages'
70
		);
71
	}
72
73
	/**
74
	 * Determines if a given path is writable in the current environment
75
	 *
76
	 * @param   string  $path  Path to check
77
	 *
78
	 * @return  boolean  True if writable
79
	 *
80
	 * @since   4.0
81
	 */
82
	public static function isWritable($path)
83
	{
84
		if (JFactory::getConfig()->get('config.ftp_enable'))
85
		{
86
			return true;
87
		}
88
		else
89
		{
90
			while (!file_exists($path))
91
			{
92
				$path = dirname($path);
93
			}
94
95
			return is_writable($path) || JPath::isOwner($path) || JPath::canChmod($path);
96
		}
97
	}
98
99
	/**
100
	 * Check if the installation path exists
101
	 *
102
	 * @return  boolean  True if the installation path exists
103
	 *
104
	 * @since   4.0
105
	 */
106
	public static function hasInstallation()
107
	{
108
		return is_dir(LOCALISEPATH_INSTALLATION);
109
	}
110
111
	/**
112
	 * Retrieve the packages array
113
	 *
114
	 * @return  array
115
	 *
116
	 * @since   4.0
117
	 */
118
	public static function getPackages()
119
	{
120
		if (empty(static::$packages))
121
		{
122
			static::scanPackages();
123
		}
124
125
		return static::$packages;
126
	}
127
128
	/**
129
	 * Scans the filesystem for language files in each package
130
	 *
131
	 * @return  void
132
	 *
133
	 * @since   4.0
134
	 */
135
	protected static function scanPackages()
136
	{
137
		$model         = JModelLegacy::getInstance('Packages', 'LocaliseModel', array('ignore_request' => true));
138
		$model->setState('list.start', 0);
139
		$model->setState('list.limit', 0);
140
		$packages       = $model->getItems();
141
142
		foreach ($packages as $package)
143
		{
144
			static::$packages[$package->name] = $package;
145
146
			foreach ($package->administrator as $file)
147
			{
148
				static::$origins['administrator'][$file] = $package->name;
149
			}
150
151
			foreach ($package->site as $file)
152
			{
153
				static::$origins['site'][$file] = $package->name;
154
			}
155
		}
156
	}
157
158
	/**
159
	 * Retrieves the origin information
160
	 *
161
	 * @param   string  $filename  The filename to check
162
	 * @param   string  $client    The client to check
163
	 *
164
	 * @return  string  Origin data
165
	 *
166
	 * @since   4.0
167
	 */
168
	public static function getOrigin($filename, $client)
169
	{
170
		if ($filename == 'override')
171
		{
172
			return '_override';
173
		}
174
175
		// If the $origins array doesn't contain data, fill it
176
		if (empty(static::$origins['site']))
177
		{
178
			static::scanPackages();
179
		}
180
181
		if (isset(static::$origins[$client][$filename]))
182
		{
183
			return static::$origins[$client][$filename];
184
		}
185
		else
186
		{
187
			return '_thirdparty';
188
		}
189
	}
190
191
	/**
192
	 * Scans the filesystem
193
	 *
194
	 * @param   string  $client  The client to scan
195
	 * @param   string  $type    The extension type to scan
196
	 *
197
	 * @return  array
198
	 *
199
	 * @since   4.0
200
	 */
201
	public static function getScans($client = '', $type = '')
202
	{
203
		$params   = JComponentHelper::getParams('com_localise');
204
		$suffixes = explode(',', $params->get('suffixes', '.sys'));
205
206
		$filter_type   = $type ? $type : '.';
207
		$filter_client = $client ? $client : '.';
208
		$scans         = array();
209
210
		// Scan installation folders
211
		if (preg_match("/$filter_client/", 'installation'))
212
		{
213
			// TODO ;-)
214
		}
215
216
		// Scan administrator folders
217
		if (preg_match("/$filter_client/", 'administrator'))
218
		{
219
			// Scan administrator components folders
220 View Code Duplication
			if (preg_match("/$filter_type/", 'component'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
			{
222
				$scans[] = array(
223
					'prefix' => '',
224
					'suffix' => '',
225
					'type'   => 'component',
226
					'client' => 'administrator',
227
					'path'   => LOCALISEPATH_ADMINISTRATOR . '/components/',
228
					'folder' => ''
229
				);
230
231
				foreach ($suffixes as $suffix)
232
				{
233
					$scans[] = array(
234
						'prefix' => '',
235
						'suffix' => $suffix,
236
						'type'   => 'component',
237
						'client' => 'administrator',
238
						'path'   => LOCALISEPATH_ADMINISTRATOR . '/components/',
239
						'folder' => ''
240
					);
241
				}
242
			}
243
244
			// Scan administrator modules folders
245 View Code Duplication
			if (preg_match("/$filter_type/", 'module'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
246
			{
247
				$scans[] = array(
248
					'prefix' => '',
249
					'suffix' => '',
250
					'type'   => 'module',
251
					'client' => 'administrator',
252
					'path'   => LOCALISEPATH_ADMINISTRATOR . '/modules/',
253
					'folder' => ''
254
				);
255
256
				foreach ($suffixes as $suffix)
257
				{
258
					$scans[] = array(
259
						'prefix' => '',
260
						'suffix' => $suffix,
261
						'type'   => 'module',
262
						'client' => 'administrator',
263
						'path'   => LOCALISEPATH_ADMINISTRATOR . '/modules/',
264
						'folder' => ''
265
					);
266
				}
267
			}
268
269
			// Scan administrator templates folders
270 View Code Duplication
			if (preg_match("/$filter_type/", 'template'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
			{
272
				$scans[] = array(
273
					'prefix' => 'tpl_',
274
					'suffix' => '',
275
					'type'   => 'template',
276
					'client' => 'administrator',
277
					'path'   => LOCALISEPATH_ADMINISTRATOR . '/templates/',
278
					'folder' => ''
279
				);
280
281
				foreach ($suffixes as $suffix)
282
				{
283
					$scans[] = array(
284
						'prefix' => 'tpl_',
285
						'suffix' => $suffix,
286
						'type'   => 'template',
287
						'client' => 'administrator',
288
						'path'   => LOCALISEPATH_ADMINISTRATOR . '/templates/',
289
						'folder' => ''
290
					);
291
				}
292
			}
293
294
			// Scan plugins folders
295
			if (preg_match("/$filter_type/", 'plugin'))
296
			{
297
				$plugin_types = JFolder::folders(JPATH_PLUGINS);
298
299
				foreach ($plugin_types as $plugin_type)
300
				{
301
					// Scan administrator language folders as this is where plugin languages are installed
302
					$scans[] = array(
303
						'prefix' => 'plg_' . $plugin_type . '_',
304
						'suffix' => '',
305
						'type'   => 'plugin',
306
						'client' => 'administrator',
307
						'path'   => JPATH_PLUGINS . "/$plugin_type/",
308
						'folder' => ''
309
					);
310
311
					foreach ($suffixes as $suffix)
312
					{
313
						$scans[] = array(
314
							'prefix' => 'plg_' . $plugin_type . '_',
315
							'suffix' => $suffix,
316
							'type'   => 'plugin',
317
							'client' => 'administrator',
318
							'path'   => JPATH_PLUGINS . "/$plugin_type/",
319
							'folder' => ''
320
						);
321
					}
322
				}
323
			}
324
		}
325
326
		// Scan site folders
327
		if (preg_match("/$filter_client/", 'site'))
328
		{
329
			// Scan site components folders
330 View Code Duplication
			if (preg_match("/$filter_type/", 'component'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
331
			{
332
				$scans[] = array(
333
					'prefix' => '',
334
					'suffix' => '',
335
					'type'   => 'component',
336
					'client' => 'site',
337
					'path'   => LOCALISEPATH_SITE . '/components/',
338
					'folder' => ''
339
				);
340
341
				foreach ($suffixes as $suffix)
342
				{
343
					$scans[] = array(
344
						'prefix' => '',
345
						'suffix' => $suffix,
346
						'type'   => 'component',
347
						'client' => 'site',
348
						'path'   => LOCALISEPATH_SITE . '/components/',
349
						'folder' => ''
350
					);
351
				}
352
			}
353
354
			// Scan site modules folders
355 View Code Duplication
			if (preg_match("/$filter_type/", 'module'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
356
			{
357
				$scans[] = array(
358
					'prefix' => '',
359
					'suffix' => '',
360
					'type'   => 'module',
361
					'client' => 'site',
362
					'path'   => LOCALISEPATH_SITE . '/modules/',
363
					'folder' => ''
364
				);
365
366
				foreach ($suffixes as $suffix)
367
				{
368
					$scans[] = array(
369
						'prefix' => '',
370
						'suffix' => $suffix,
371
						'type'   => 'module',
372
						'client' => 'site',
373
						'path'   => LOCALISEPATH_SITE . '/modules/',
374
						'folder' => ''
375
					);
376
				}
377
			}
378
379
			// Scan site templates folders
380 View Code Duplication
			if (preg_match("/$filter_type/", 'template'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
381
			{
382
				$scans[] = array(
383
					'prefix' => 'tpl_',
384
					'suffix' => '',
385
					'type'   => 'template',
386
					'client' => 'site',
387
					'path'   => LOCALISEPATH_SITE . '/templates/',
388
					'folder' => ''
389
				);
390
391
				foreach ($suffixes as $suffix)
392
				{
393
					$scans[] = array(
394
						'prefix' => 'tpl_',
395
						'suffix' => $suffix,
396
						'type'   => 'template',
397
						'client' => 'site',
398
						'path'   => LOCALISEPATH_SITE . '/templates/',
399
						'folder' => ''
400
					);
401
				}
402
			}
403
		}
404
405
		return $scans;
406
	}
407
408
	/**
409
	 * Get file ID in the database for the given file path
410
	 *
411
	 * @param   string  $path  Path to lookup
412
	 *
413
	 * @return  integer  File ID
414
	 *
415
	 * @since   4.0
416
	 */
417
	public static function getFileId($path)
418
	{
419
		static $fileIds = null;
420
421 View Code Duplication
		if (!isset($fileIds))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
422
		{
423
			$db = JFactory::getDbo();
424
425
			$db->setQuery(
426
				$db->getQuery(true)
427
					->select($db->quoteName(array('id', 'path')))
428
					->from($db->quoteName('#__localise'))
429
			);
430
431
			$fileIds = $db->loadObjectList('path');
432
		}
433
434
		if (is_file($path) || preg_match('/.ini$/', $path))
435
		{
436
			if (!array_key_exists($path, $fileIds))
437
			{
438
				JTable::addIncludePath(JPATH_COMPONENT . '/tables');
439
440
				/* @type  LocaliseTableLocalise  $table */
441
				$table       = JTable::getInstance('Localise', 'LocaliseTable');
442
				$table->path = $path;
443
				$table->store();
444
445
				$fileIds[$path] = new stdClass;
446
				$fileIds[$path]->id = $table->id;
447
			}
448
449
			return $fileIds[$path]->id;
450
		}
451
		else
452
		{
453
			$id = 0;
454
		}
455
456
		return $id;
457
	}
458
459
	/**
460
	 * Get file path in the database for the given file id
461
	 *
462
	 * @param   integer  $id  Id to lookup
463
	 *
464
	 * @return  string   File Path
465
	 *
466
	 * @since   4.0
467
	 */
468
	public static function getFilePath($id)
469
	{
470
		static $filePaths = null;
471
472 View Code Duplication
		if (!isset($filePaths))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
473
		{
474
			$db = JFactory::getDbo();
475
476
			$db->setQuery(
477
				$db->getQuery(true)
478
					->select($db->quoteName(array('id', 'path')))
479
					->from($db->quoteName('#__localise'))
480
			);
481
482
			$filePaths = $db->loadObjectList('id');
483
		}
484
485
		return array_key_exists("$id", $filePaths) ?
486
		$filePaths["$id"]->path : '';
487
	}
488
489
	/**
490
	 * Determine if a package at given path is core or not.
491
	 *
492
	 * @param   string  $path  Path to lookup
493
	 *
494
	 * @return  mixed  null if file is invalid | True if core else false.
495
	 *
496
	 * @since   4.0
497
	 */
498
	public static function isCorePackage($path)
499
	{
500
		if (is_file($path) || preg_match('/.ini$/', $path))
501
		{
502
			$xml = simplexml_load_file($path);
503
504
			return ((string) $xml->attributes()->core) == 'true';
505
		}
506
	}
507
508
	/**
509
	 * Find a translation file
510
	 *
511
	 * @param   string  $client    Client to lookup
512
	 * @param   string  $tag       Language tag to lookup
513
	 * @param   string  $filename  Filename to lookup
514
	 *
515
	 * @return  string  Path to the requested file
516
	 *
517
	 * @since   4.0
518
	 */
519
	public static function findTranslationPath($client, $tag, $filename)
520
	{
521
		$params = JComponentHelper::getParams('com_localise');
522
		$priority = $params->get('priority', '0') == '0' ? 'global' : 'local';
523
		$path = static::getTranslationPath($client, $tag, $filename, $priority);
524
525
		if (!is_file($path))
526
		{
527
			$priority = $params->get('priority', '0') == '0' ? 'local' : 'global';
528
			$path = static::getTranslationPath($client, $tag, $filename, $priority);
529
		}
530
531
		return $path;
532
	}
533
534
	/**
535
	 * Get a translation path
536
	 *
537
	 * @param   string  $client    Client to lookup
538
	 * @param   string  $tag       Language tag to lookup
539
	 * @param   string  $filename  Filename to lookup
540
	 * @param   string  $storage   Storage location to check
541
	 *
542
	 * @return  string  Path to the requested file
543
	 *
544
	 * @since   4.0
545
	 */
546
	public static function getTranslationPath($client, $tag, $filename, $storage)
547
	{
548
		if ($filename == 'override')
549
		{
550
			$path = constant('LOCALISEPATH_' . strtoupper($client)) . "/language/overrides/$tag.override.ini";
551
		}
552
		elseif ($filename == 'joomla')
553
		{
554
			$path = constant('LOCALISEPATH_' . strtoupper($client)) . "/language/$tag/$tag.ini";
555
		}
556
		elseif ($storage == 'global')
557
		{
558
			$path = constant('LOCALISEPATH_' . strtoupper($client)) . "/language/$tag/$tag.$filename.ini";
559
		}
560
		else
561
		{
562
			$parts     = explode('.', $filename);
563
			$extension = $parts[0];
564
565
			switch (substr($extension, 0, 3))
566
			{
567 View Code Duplication
				case 'com':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
568
					$path = constant('LOCALISEPATH_' . strtoupper($client)) . "/components/$extension/language/$tag/$tag.$filename.ini";
569
570
					break;
571
572 View Code Duplication
				case 'mod':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
573
					$path = constant('LOCALISEPATH_' . strtoupper($client)) . "/modules/$extension/language/$tag/$tag.$filename.ini";
574
575
					break;
576
577
				case 'plg':
578
					$parts  = explode('_', $extension);
579
					$group  = $parts[1];
580
					$parts	= explode('.', $filename);
581
					$pluginname = $parts[0];
582
					$plugin = substr($pluginname, 5 + strlen($group));
583
					$path   = JPATH_PLUGINS . "/$group/$plugin/language/$tag/$tag.$filename.ini";
584
585
					break;
586
587 View Code Duplication
				case 'tpl':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
588
					$template = substr($extension, 4);
589
					$path     = constant('LOCALISEPATH_' . strtoupper($client)) . "/templates/$template/language/$tag/$tag.$filename.ini";
590
591
					break;
592
593
				case 'lib':
594
					$path = constant('LOCALISEPATH_' . strtoupper($client)) . "/language/$tag/$tag.$filename.ini";
595
596
					if (!is_file($path))
597
					{
598
						$path = $client == 'administrator' ? 'LOCALISEPATH_' . 'SITE' : 'LOCALISEPATH_' . 'ADMINISTRATOR' . "/language/$tag/$tag.$filename.ini";
599
					}
600
601
					break;
602
603
				default   :
604
					$path = '';
605
606
					break;
607
			}
608
		}
609
610
		return $path;
611
	}
612
613
	/**
614
	 * Load a language file for translating the package name
615
	 *
616
	 * @param   string  $extension  The extension to load
617
	 * @param   string  $client     The client from where to load the file
618
	 *
619
	 * @return  void
620
	 *
621
	 * @since   4.0
622
	 */
623
	public static function loadLanguage($extension, $client)
624
	{
625
		$extension = strtolower($extension);
626
		$lang      = JFactory::getLanguage();
627
		$prefix    = substr($extension, 0, 3);
628
629
		switch ($prefix)
630
		{
631 View Code Duplication
			case 'com':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
632
				$lang->load($extension, constant('LOCALISEPATH_' . strtoupper($client)), null, false, true)
633
					|| $lang->load($extension, constant('LOCALISEPATH_' . strtoupper($client)) . "/components/$extension/", null, false, true);
634
635
				break;
636
637 View Code Duplication
			case 'mod':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
638
				$lang->load($extension, constant('LOCALISEPATH_' . strtoupper($client)), null, false, true)
639
					|| $lang->load($extension, constant('LOCALISEPATH_' . strtoupper($client)) . "/modules/$extension/", null, false, true);
640
641
				break;
642
643
			case 'plg':
644
				$lang->load($extension, 'LOCALISEPATH_' . 'ADMINISTRATOR', null, false, true)
645
					|| $lang->load($extension, LOCALISEPATH_ADMINISTRATOR . "/components/$extension/", null, false, true);
646
647
				break;
648
649 View Code Duplication
			case 'tpl':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
650
				$template = substr($extension, 4);
651
				$lang->load($extension, constant('LOCALISEPATH_' . strtoupper($client)), null, false, true)
652
					|| $lang->load($extension, constant('LOCALISEPATH_' . strtoupper($client)) . "/templates/$template/", null, false, true);
653
654
				break;
655
656
			case 'lib':
657
			case 'fil':
658
			case 'pkg':
659
				$lang->load($extension, JPATH_ROOT, null, false, true);
660
661
				break;
662
		}
663
	}
664
665
	/**
666
	 * Parses the sections of a language file
667
	 *
668
	 * @param   string  $filename  The filename to parse
669
	 *
670
	 * @return  array  Array containing the file data
671
	 *
672
	 * @since   4.0
673
	 */
674
	public static function parseSections($filename)
675
	{
676
		static $sections = array();
677
678
		if (!array_key_exists($filename, $sections))
679
		{
680
			if (file_exists($filename))
681
			{
682
				$error = '';
683
684
				if (!defined('_QQ_'))
685
				{
686
					define('_QQ_', '"');
687
				}
688
689
				ini_set('track_errors', '1');
690
691
				$contents = file_get_contents($filename);
692
				$contents = str_replace('_QQ_', '"\""', $contents);
693
				$strings  = @parse_ini_string($contents, true);
694
695
				if (!empty($php_errormsg))
696
				{
697
					$error = "Error parsing " . basename($filename) . ": $php_errormsg";
698
				}
699
700
				ini_restore('track_errors');
701
702
				if ($strings !== false)
703
				{
704
					$default = array();
705
706
					foreach ($strings as $key => $value)
707
					{
708
						if (is_string($value))
709
						{
710
							$default[$key] = $value;
711
712
							unset($strings[$key]);
713
						}
714
						else
715
						{
716
							break;
717
						}
718
					}
719
720
					if (!empty($default))
721
					{
722
						$strings = array_merge(array('Default' => $default), $strings);
723
					}
724
725
					$keys = array();
726
727
					foreach ($strings as $section => $value)
728
					{
729
						foreach ($value as $key => $string)
730
						{
731
							$keys[$key] = $strings[$section][$key];
732
						}
733
					}
734
				}
735
				else
736
				{
737
					$keys = false;
738
				}
739
740
				$sections[$filename] = array('sections' => $strings, 'keys' => $keys, 'error' => $error);
741
			}
742
			else
743
			{
744
				$sections[$filename] = array('sections' => array(), 'keys' => array(), 'error' => '');
745
			}
746
		}
747
748
		if (!empty($sections[$filename]['error']))
749
		{
750
			$model = JModelLegacy::getInstance('Translation', 'LocaliseModel');
751
			$model->setError($sections[$filename]['error']);
752
		}
753
754
		return $sections[$filename];
755
	}
756
757
	/**
758
	 * Gets the files to use as source reference from Github
759
	 *
760
	 * @param   array  $gh_data  Array with the required data
761
	 *
762
	 * @return  array
763
	 *
764
	 * @since   4.11
765
	 */
766
	public static function getSourceGithubfiles($gh_data = array())
767
	{
768
		if (!empty($gh_data))
769
		{
770
			$params        = JComponentHelper::getParams('com_localise');
771
			$ref_tag       = $params->get('reference', 'en-GB');
772
			$saved_ref     = $params->get('customisedref', '0');
773
			$allow_develop = $params->get('gh_allow_develop', 0);
774
			$gh_client     = $gh_data['github_client'];
775
			$customisedref = $saved_ref;
776
			$last_sources  = self::getLastsourcereference();
777
			$last_source   = $last_sources[$gh_client];
778
779
			$versions_path = JPATH_ROOT
780
					. '/administrator/components/com_localise/customisedref/stable_joomla_releases.txt';
781
782
			$versions_file = file_get_contents($versions_path);
783
			$versions      = preg_split("/\\r\\n|\\r|\\n/", $versions_file);
784
785
			if ($saved_ref != '0' && !in_array($customisedref, $versions))
786
			{
787
				// Ensure from translations view that we have updated the last one released only when no maches.
788
				$search_releases = self::getReleases();
0 ignored issues
show
Unused Code introduced by
$search_releases is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
789
				$versions_file   = file_get_contents($versions_path);
790
				$versions        = preg_split("/\\r\\n|\\r|\\n/", $versions_file);
791
			}
792
793
			$installed_version = new JVersion;
794
			$installed_version = $installed_version->getShortVersion();
795
796
			$core_paths['administrator'] = 'administrator/language/en-GB';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$core_paths was never initialized. Although not strictly required by PHP, it is generally a good practice to add $core_paths = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
797
			$core_paths['site']          = 'language/en-GB';
798
			$core_paths['installation']  = 'installation/language/en-GB';
799
800
			if ($saved_ref == '0')
801
			{
802
				// It will use core language folders.
803
				$customisedref = "Local installed instance ($installed_version??)";
804
			}
805
			else
806
			{
807
				// It will use language folders with other stored versions.
808
				$custom_client_path = JPATH_ROOT . '/media/com_localise/customisedref/github/'
809
						. $gh_data['github_client']
810
						. '/'
811
						. $customisedref;
812
				$custom_client_path = JFolder::makeSafe($custom_client_path);
813
			}
814
815
			// If reference tag is not en-GB is not required try it
816
			if ($ref_tag != 'en-GB' && $allow_develop == 1)
817
			{
818
				JFactory::getApplication()->enqueueMessage(
819
					JText::_('COM_LOCALISE_ERROR_GETTING_UNALLOWED_CONFIGURATION'),
820
					'warning');
821
822
				return false;
823
			}
824
825
			// If not knowed Joomla version is not required try it
826
			if ($saved_ref != '0' && !in_array($customisedref, $versions) && $allow_develop == 1)
827
			{
828
				JFactory::getApplication()->enqueueMessage(
829
					JText::sprintf('COM_LOCALISE_ERROR_GITHUB_GETTING_LOCAL_INSTALLED_FILES', $customisedref),
830
					'warning');
831
832
				$option    = '0';
833
				$revert    = self::setCustomisedsource($option);
0 ignored issues
show
Unused Code introduced by
$revert is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
834
				$save_last = self::saveLastsourcereference($gh_data['github_client'], '');
0 ignored issues
show
Unused Code introduced by
$save_last is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
835
836
				return false;
837
			}
838
839
			// If feature is disabled but last used files are disctinct to default ones
840
			// Is required make notice that we are coming back to local installed instance version.
841
			if ($saved_ref != '0' && !empty($last_source) && $last_source != '0' && $allow_develop == 0)
842
			{
843
				$customisedref = $installed_version;
0 ignored issues
show
Unused Code introduced by
$customisedref is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
844
845
				JFactory::getApplication()->enqueueMessage(
846
					JText::sprintf('COM_LOCALISE_NOTICE_DISABLED_ALLOW_DEVELOP_WITHOUT_LOCAL_SET',
847
						$last_source,
848
						$installed_version,
849
						$gh_client
850
						),
851
						'notice'
852
						);
853
854
				$option    = '0';
855
				$revert    = self::setCustomisedsource($option);
0 ignored issues
show
Unused Code introduced by
$revert is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
856
				$save_last = self::saveLastsourcereference($gh_data['github_client'], '');
0 ignored issues
show
Unused Code introduced by
$save_last is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
857
858
				return true;
859
			}
860
861
			// If not knowed Joomla version and feature is disabled is not required try it
862
			if ($saved_ref != '0' && !in_array($customisedref, $versions) && $allow_develop == 0)
863
			{
864
				return false;
865
			}
866
867
			// If configured to local installed instance there is nothing to get from Github
868
			if ($saved_ref == '0')
869
			{
870
				$save_last = self::saveLastsourcereference($gh_data['github_client'], '');
0 ignored issues
show
Unused Code introduced by
$save_last is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
871
872
				return true;
873
			}
874
875
			$xml_file = $custom_client_path . '/en-GB.xml';
0 ignored issues
show
Bug introduced by
The variable $custom_client_path does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
876
877
			// Unrequired move or update files again
878
			if ($saved_ref != '0' && $installed_version == $last_source && JFile::exists($xml_file))
879
			{
880
				return false;
881
			}
882
883
			$gh_data['allow_develop']  = $allow_develop;
884
			$gh_data['customisedref']  = $customisedref;
885
			$gh_target                 = self::getCustomisedsource($gh_data);
886
			$gh_paths                  = array();
887
			$gh_user                   = $gh_target['user'];
888
			$gh_project                = $gh_target['project'];
889
			$gh_branch                 = $gh_target['branch'];
890
			$gh_token                  = $params->get('gh_token', '');
891
			$gh_paths['administrator'] = 'administrator/language/en-GB';
892
			$gh_paths['site']          = 'language/en-GB';
893
			$gh_paths['installation']  = 'installation/language/en-GB';
894
895
			$reference_client_path = JPATH_ROOT . '/' . $gh_paths[$gh_client];
896
			$reference_client_path = JFolder::makeSafe($reference_client_path);
897
898
			if (JFile::exists($xml_file))
899
			{
900
				// We have done this trunk and is not required get the files from Github again.
901
				$update_files = self::updateSourcereference($gh_client, $custom_client_path);
902
903
				if ($update_files == false)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
904
				{
905
					return false;
906
				}
907
908
				$save_last = self::saveLastsourcereference($gh_data['github_client'], $customisedref);
0 ignored issues
show
Unused Code introduced by
$save_last is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
909
910
				return true;
911
			}
912
913
			$options = new JRegistry;
914
915 View Code Duplication
			if (!empty($gh_token))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
916
			{
917
				$options->set('gh.token', $gh_token);
918
				$github = new Github($options);
919
			}
920
			else
921
			{
922
				// Without a token runs fatal.
923
				// $github = new JGithub;
924
925
				// Trying with a 'read only' public repositories token
926
				// But base 64 encoded to avoid Github alarms sharing it.
927
				$gh_token = base64_decode('MzY2NzYzM2ZkMzZmMWRkOGU5NmRiMTdjOGVjNTFiZTIyMzk4NzVmOA==');
928
				$options->set('gh.token', $gh_token);
929
				$github = new Github($options);
930
			}
931
932
			try
933
			{
934
				$repostoryfiles = $github->repositories->contents->get(
935
					$gh_user,
936
					$gh_project,
937
					$gh_paths[$gh_client],
938
					$gh_branch
939
					);
940
			}
941
			catch (Exception $e)
942
			{
943
				JFactory::getApplication()->enqueueMessage(
944
					JText::_('COM_LOCALISE_ERROR_GITHUB_GETTING_REPOSITORY_FILES'),
945
					'warning');
946
947
				return false;
948
			}
949
950
			if (!JFolder::exists($custom_client_path))
951
			{
952
				$create_folder = self::createFolder($gh_data, $index = 'true');
953
954
				if ($create_folder == false)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
955
				{
956
					return false;
957
				}
958
			}
959
960
			$all_files_list = self::getLanguagefileslist($custom_client_path);
961
			$ini_files_list = self::getInifileslist($custom_client_path);
0 ignored issues
show
Unused Code introduced by
$ini_files_list is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
962
963
			$files_to_include = array();
964
965
			foreach ($repostoryfiles as $repostoryfile)
966
			{
967
				$file_to_include = $repostoryfile->name;
968
				$file_path = JFolder::makeSafe($custom_client_path . '/' . $file_to_include);
969
				$reference_file_path = JFolder::makeSafe($reference_client_path . '/' . $file_to_include);
0 ignored issues
show
Unused Code introduced by
$reference_file_path is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
970
971
				$custom_file = $github->repositories->contents->get(
972
						$gh_user,
973
						$gh_project,
974
						$repostoryfile->path,
975
						$gh_branch
976
						);
977
978
				$files_to_include[] = $file_to_include;
979
980
				if (!empty($custom_file) && isset($custom_file->content))
981
				{
982
					$file_to_include = $repostoryfile->name;
0 ignored issues
show
Unused Code introduced by
$file_to_include is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
983
					$file_contents   = base64_decode($custom_file->content);
984
					JFile::write($file_path, $file_contents);
985
986
					if (!JFile::exists($file_path))
987
					{
988
						JFactory::getApplication()->enqueueMessage(
989
							JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_CREATE_DEV_FILE'),
990
							'warning');
991
992
						return false;
993
					}
994
				}
995
			}
996
997
			if (!empty($all_files_list) && !empty($files_to_include))
998
			{
999
				// For files not present yet.
1000
				$files_to_delete = array_diff($all_files_list, $files_to_include);
1001
1002
				if (!empty($files_to_delete))
1003
				{
1004
					foreach ($files_to_delete as $file_to_delete)
1005
					{
1006
						if ($file_to_delete != 'index.html')
1007
						{
1008
							$file_path = JFolder::makeSafe($custom_client_path . "/" . $file_to_delete);
1009
							JFile::delete($file_path);
1010
1011
							if (JFile::exists($file_path))
1012
							{
1013
								JFactory::getApplication()->enqueueMessage(
1014
									JText::_('COM_LOCALISE_ERROR_GITHUB_FILE_TO_DELETE_IS_PRESENT'),
1015
									'warning');
1016
1017
								return false;
1018
							}
1019
						}
1020
					}
1021
				}
1022
			}
1023
1024
			if (JFile::exists($xml_file))
1025
			{
1026
				// We have done this trunk.
1027
1028
				// So we can move the customised source reference files to core client folder
1029
				$update_files = self::updateSourcereference($gh_client, $custom_client_path);
1030
1031
				if ($update_files == false)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1032
				{
1033
					return false;
1034
				}
1035
1036
				$save_last = self::saveLastsourcereference($gh_data['github_client'], $customisedref);
0 ignored issues
show
Unused Code introduced by
$save_last is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1037
1038
				JFactory::getApplication()->enqueueMessage(
1039
					JText::sprintf('COM_LOCALISE_NOTICE_GITHUB_GETS_A_SOURCE_FULL_SET', $customisedref),
1040
					'notice');
1041
1042
				return true;
1043
			}
1044
1045
			JFactory::getApplication()->enqueueMessage(
1046
				JText::sprintf('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_GET_A_FULL_SOURCE_SET', $customisedref),
1047
				'warning');
1048
1049
			return false;
1050
		}
1051
1052
		JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_GITHUB_NO_DATA_PRESENT'), 'warning');
1053
1054
		return false;
1055
	}
1056
1057
	/**
1058
	 * Gets the stable Joomla releases list.
1059
	 *
1060
	 * @return  array
1061
	 *
1062
	 * @since   4.11
1063
	 */
1064
	public static function getReleases()
1065
	{
1066
		$params        = JComponentHelper::getParams('com_localise');
1067
		$versions_path = JPATH_ROOT
1068
				. '/administrator/components/com_localise/customisedref/stable_joomla_releases.txt';
1069
		$versions_file = file_get_contents($versions_path);
1070
		$versions      = preg_split("/\\r\\n|\\r|\\n/", $versions_file);
1071
1072
		$gh_user       = 'joomla';
1073
		$gh_project    = 'joomla-cms';
1074
		$gh_token      = $params->get('gh_token', '');
1075
1076
		$options = new JRegistry;
1077
1078 View Code Duplication
		if (!empty($gh_token))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1079
		{
1080
			$options->set('gh.token', $gh_token);
1081
			$github = new Github($options);
1082
		}
1083
		else
1084
		{
1085
			// Without a token runs fatal.
1086
			// $github = new JGithub;
1087
1088
			// Trying with a 'read only' public repositories token
1089
			// But base 64 encoded to avoid Github alarms sharing it.
1090
			$gh_token = base64_decode('MzY2NzYzM2ZkMzZmMWRkOGU5NmRiMTdjOGVjNTFiZTIyMzk4NzVmOA==');
1091
			$options->set('gh.token', $gh_token);
1092
			$github = new Github($options);
1093
		}
1094
1095
		try
1096
		{
1097
			$releases = $github->repositories->get(
1098
					$gh_user,
1099
					$gh_project . '/releases'
1100
					);
1101
1102 View Code Duplication
			foreach ($releases as $release)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1103
			{
1104
				$tag_name = $release->tag_name;
1105
				$tag_part = explode(".", $tag_name);
1106
				$undoted  = str_replace('.', '', $tag_name);
1107
				$excluded = 0;
1108
1109
				if (version_compare(JVERSION[0], '2', 'eq'))
1110
				{
1111
					$excluded = 1;
1112
				}
1113
				elseif (version_compare(JVERSION[0], '3', 'eq'))
1114
				{
1115
					if ($tag_part[0] != '3')
1116
					{
1117
						$excluded = 1;
1118
					}
1119
				}
1120
				elseif (version_compare(JVERSION[0], '4', 'ge'))
1121
				{
1122
					if ($tag_part[0] == '4' || $tag_part[0] == '3')
1123
					{
1124
						$excluded = 0;
1125
					}
1126
					else
1127
					{
1128
						$excluded = 1;
1129
					}
1130
				}
1131
1132
				// Filtering by "is_numeric" disable betas or similar releases.
1133
				if ($params->get('pre_stable', '0') == '0')
1134
				{
1135
					if (!in_array($tag_name, $versions) && is_numeric($undoted) && $excluded == 0)
1136
					{
1137
						$versions[] = $tag_name;
1138
						JFactory::getApplication()->enqueueMessage(
1139
							JText::sprintf('COM_LOCALISE_NOTICE_NEW_VERSION_DETECTED', $tag_name),
1140
							'notice');
1141
					}
1142
				}
1143
				else
1144
				{
1145
					if (!in_array($tag_name, $versions) && $excluded == 0)
1146
					{
1147
						$versions[] = $tag_name;
1148
						JFactory::getApplication()->enqueueMessage(
1149
							JText::sprintf('COM_LOCALISE_NOTICE_NEW_VERSION_DETECTED', $tag_name),
1150
							'notice');
1151
					}
1152
				}
1153
			}
1154
		}
1155
		catch (Exception $e)
1156
		{
1157
			JFactory::getApplication()->enqueueMessage(
1158
				JText::_('COM_LOCALISE_ERROR_GITHUB_GETTING_RELEASES'),
1159
				'warning');
1160
		}
1161
1162
		arsort($versions);
1163
1164
		$versions_file = '';
1165
1166
		foreach ($versions as $id => $version)
1167
		{
1168
			if (!empty($version))
1169
			{
1170
				$versions_file .= $version . "\n";
1171
			}
1172
		}
1173
1174
		JFile::write($versions_path, $versions_file);
1175
1176
		return $versions;
1177
	}
1178
1179
	/**
1180
	 * Save the last en-GB source version used as reference.
1181
	 *
1182
	 * @param   string  $client         The client
1183
	 *
1184
	 * @param   string  $customisedref  The version number
1185
	 *
1186
	 * @return  boolean
1187
	 *
1188
	 * @since   4.11
1189
	 */
1190
	public static function saveLastsourcereference($client = '', $customisedref = '')
1191
	{
1192
		$last_reference_file = JPATH_COMPONENT_ADMINISTRATOR
1193
					. '/customisedref/'
1194
					. $client
1195
					. '_last_source_ref.txt';
1196
1197
		$file_contents = $customisedref . "\n";
1198
1199
		if (!JFile::write($last_reference_file, $file_contents))
1200
		{
1201
			return false;
1202
		}
1203
1204
		return true;
1205
	}
1206
1207
	/**
1208
	 * Gets the last en-GB source reference version moved to the core folders.
1209
	 *
1210
	 * @return  array
1211
	 *
1212
	 * @since   4.11
1213
	 */
1214
	public static function getLastsourcereference()
1215
	{
1216
		$last_source_reference = array();
1217
		$last_source_reference['administrator'] = '';
1218
		$last_source_reference['site'] = '';
1219
		$last_source_reference['installation'] = '';
1220
1221
		$clients = array('administrator', 'site', 'installation');
1222
1223
		foreach ($clients as $client)
1224
		{
1225
			$last_reference_file = JPATH_COMPONENT_ADMINISTRATOR
1226
							. '/customisedref/'
1227
							. $client
1228
							. '_last_source_ref.txt';
1229
1230
			if (JFile::exists($last_reference_file))
1231
			{
1232
				$file_contents = file_get_contents($last_reference_file);
1233
				$lines = preg_split("/\\r\\n|\\r|\\n/", $file_contents);
1234
1235
				foreach ($lines as $line)
1236
				{
1237
					if (!empty($line))
1238
					{
1239
						$last_source_reference[$client] = $line;
1240
					}
1241
				}
1242
			}
1243
		}
1244
1245
		return $last_source_reference;
1246
	}
1247
1248
	/**
1249
	 * Gets the reference name to use at Github
1250
	 *
1251
	 * @param   array  $gh_data  Array with the required data
1252
	 *
1253
	 * @return  array
1254
	 *
1255
	 * @since   4.11
1256
	 */
1257
	public static function getCustomisedsource($gh_data = array())
1258
	{
1259
		$source_ref        = $gh_data['customisedref'];
1260
		$allow_develop     = $gh_data['allow_develop'];
0 ignored issues
show
Unused Code introduced by
$allow_develop is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1261
1262
		$sources = array();
1263
1264
		// Detailing it we can handle exceptions and add other Github users or projects.
1265
		// To get the language files for a determined Joomla's version that is not present from main Github repository.
1266
		$sources['3.4.1']['user']    = 'joomla';
1267
		$sources['3.4.1']['project'] = 'joomla-cms';
1268
		$sources['3.4.1']['branch']  = '3.4.1';
1269
1270
		if (array_key_exists($source_ref, $sources))
1271
		{
1272
			return ($sources[$source_ref]);
1273
		}
1274
1275
		// For undefined REF 0 or unlisted cases due Joomla releases at Github are following a version name patern.
1276
		$sources[$source_ref]['user']    = 'joomla';
1277
		$sources[$source_ref]['project'] = 'joomla-cms';
1278
		$sources[$source_ref]['branch']  = $source_ref;
1279
1280
	return ($sources[$source_ref]);
1281
	}
1282
1283
	/**
1284
	 * Keep updated the customised client path including only the common files present in develop.
1285
	 *
1286
	 * @param   string  $client              The client
1287
	 *
1288
	 * @param   string  $custom_client_path  The path where the new source reference is stored
1289
	 *
1290
	 * @return  boolean
1291
	 *
1292
	 * @since   4.11
1293
	 */
1294
	public static function updateSourcereference($client, $custom_client_path)
1295
	{
1296
		$develop_client_path   = JPATH_ROOT . '/media/com_localise/develop/github/joomla-cms/en-GB/' . $client;
1297
		$develop_client_path   = JFolder::makeSafe($develop_client_path);
1298
1299
		$custom_ini_files_list = self::getInifileslist($custom_client_path);
1300
		$last_ini_files_list   = self::getInifileslist($develop_client_path);
1301
1302
		$files_to_exclude = array();
0 ignored issues
show
Unused Code introduced by
$files_to_exclude is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1303
1304 View Code Duplication
		if (!JFile::exists($develop_client_path . '/en-GB.xml'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1305
		{
1306
			JFactory::getApplication()->enqueueMessage(
1307
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_TARGET_FILES'),
1308
				'warning');
1309
1310
			return false;
1311
		}
1312
		elseif (!JFile::exists($custom_client_path . '/en-GB.xml'))
1313
		{
1314
			JFactory::getApplication()->enqueueMessage(
1315
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_SOURCE_FILES'),
1316
				'warning');
1317
1318
			return false;
1319
		}
1320
1321
		// This one is for files not present within last in dev yet.
1322
		// Due have no sense add old language files to translate or revise for the comming soon package.
1323
1324
		$files_to_exclude = array_diff($custom_ini_files_list, $last_ini_files_list);
1325
1326
		if (!empty($files_to_exclude))
1327
		{
1328
			$errors = 0;
1329
1330
			foreach ($files_to_exclude as $file_to_delete)
1331
			{
1332
				$custom_file_path = JFolder::makeSafe($custom_client_path . "/" . $file_to_delete);
1333
1334
				if (!JFile::delete($custom_file_path))
1335
				{
1336
					$errors++;
1337
				}
1338
			}
1339
1340
			if ($errors > 0)
1341
			{
1342
				JFactory::getApplication()->enqueueMessage(
1343
					JText::sprintf('COM_LOCALISE_ERROR_DELETING_EXTRA_SOURCE_FILES', $errors),
1344
					'warning');
1345
1346
				return false;
1347
			}
1348
		}
1349
1350
		return true;
1351
	}
1352
1353
	/**
1354
	 * Keep updated the core path with the selected source files as reference (used at previous working mode).
1355
	 *
1356
	 * @param   string  $client                 The client
1357
	 *
1358
	 * @param   string  $custom_client_path     The path where the new source reference is stored
1359
	 *
1360
	 * @param   string  $reference_client_path  The path where the old source reference is stored
1361
	 *
1362
	 * @return  boolean
1363
	 *
1364
	 * @since   4.11
1365
	 */
1366
	public static function updateSourcereferencedirectly($client, $custom_client_path, $reference_client_path)
1367
	{
1368
		$develop_client_path   = JPATH_ROOT . '/media/com_localise/develop/github/joomla-cms/en-GB/' . $client;
1369
		$develop_client_path   = JFolder::makeSafe($develop_client_path);
1370
1371
		$custom_ini_files_list = self::getInifileslist($custom_client_path);
1372
		$last_ini_files_list   = self::getInifileslist($develop_client_path);
1373
1374
		$files_to_exclude = array();
0 ignored issues
show
Unused Code introduced by
$files_to_exclude is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1375
1376 View Code Duplication
		if (!JFile::exists($develop_client_path . '/en-GB.xml'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1377
		{
1378
			JFactory::getApplication()->enqueueMessage(
1379
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_TARGET_FILES'),
1380
				'warning');
1381
1382
			return false;
1383
		}
1384
		elseif (!JFile::exists($custom_client_path . '/en-GB.xml'))
1385
		{
1386
			JFactory::getApplication()->enqueueMessage(
1387
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_SOURCE_FILES'),
1388
				'warning');
1389
1390
			return false;
1391
		}
1392
1393
		// This one is for core files not present within last in dev yet.
1394
		// Due have no sense add old language files to translate for the comming soon package.
1395
1396
		$files_to_exclude = array_diff($custom_ini_files_list, $last_ini_files_list);
1397
1398
		if (!empty($files_to_exclude))
1399
		{
1400
			foreach ($files_to_exclude as $file_to_delete)
1401
			{
1402
				$custom_file_path = JFolder::makeSafe($custom_client_path . "/" . $file_to_delete);
1403
				$actual_file_path = JFolder::makeSafe($reference_client_path . "/" . $file_to_delete);
1404
1405
				JFile::delete($custom_file_path);
1406
1407
				// Also verify if the same file is also present in core language folder.
1408
1409
				if (JFile::exists($actual_file_path))
1410
				{
1411
					JFile::delete($actual_file_path);
1412
1413
					JFactory::getApplication()->enqueueMessage(
1414
					JText::sprintf('COM_LOCALISE_OLD_FILE_DELETED', $file_to_delete),
1415
					'notice');
1416
				}
1417
			}
1418
1419
			// Getting the new list again
1420
			$custom_ini_files_list = self::getInifileslist($custom_client_path);
1421
		}
1422
1423
		$errors = 0;
1424
1425
		foreach ($custom_ini_files_list as $customised_source_file)
1426
		{
1427
			$source_path = $custom_client_path . '/' . $customised_source_file;
1428
			$file_contents = file_get_contents($source_path);
1429
			$target_path = $reference_client_path . '/' . $customised_source_file;
1430
1431
			if (!JFile::write($target_path, $file_contents))
1432
			{
1433
				$errors++;
1434
			}
1435
		}
1436
1437
		if ($errors > 0)
1438
		{
1439
			JFactory::getApplication()->enqueueMessage(
1440
				JText::sprintf('COM_LOCALISE_ERROR_SAVING_FILES_AT_CORE_FOLDER', $errors),
1441
				'warning');
1442
1443
			return false;
1444
		}
1445
1446
		return true;
1447
	}
1448
1449
	/**
1450
	 * Gets from zero or keept updated the files in develop to use as target reference from Github
1451
	 *
1452
	 * @param   array  $gh_data  Array with the required data
1453
	 *
1454
	 * @return  array
1455
	 *
1456
	 * @since   4.11
1457
	 */
1458
	public static function getTargetgithubfiles($gh_data = array())
1459
	{
1460
		if (!empty($gh_data))
1461
		{
1462
			$now                = new JDate;
1463
			$now                = $now->toSQL();
1464
			$params             = JComponentHelper::getParams('com_localise');
1465
			$client_to_update   = 'gh_' . $gh_data['github_client'] . '_last_update';
1466
			$last_stored_update = $params->get($client_to_update, '');
1467
			$ref_tag            = $params->get('reference', 'en-GB');
1468
			$allow_develop      = $params->get('gh_allow_develop', 0);
1469
1470
			if ($allow_develop == 0)
1471
			{
1472
				return false;
1473
			}
1474
1475
			if ($ref_tag != 'en-GB')
1476
			{
1477
				JFactory::getApplication()->enqueueMessage(
1478
					JText::_('COM_LOCALISE_ERROR_GETTING_ALLOWED_REFERENCE_TAG'),
1479
					'warning');
1480
1481
				return false;
1482
			}
1483
1484
			$develop_client_path = JPATH_ROOT
1485
						. '/media/com_localise/develop/github/joomla-cms/en-GB/'
1486
						. $gh_data['github_client'];
1487
1488
			$develop_client_path = JFolder::makeSafe($develop_client_path);
1489
			$xml_file            = $develop_client_path . '/en-GB.xml';
1490
1491
			if (!JFile::exists($xml_file))
1492
			{
1493
				$get_files = 1;
1494
			}
1495
			elseif (!empty($last_stored_update))
1496
			{
1497
				$last_update = new JDate($last_stored_update);
1498
				$last_update = $last_update->toSQL();
1499
				$interval    = $params->get('gh_updates_interval', '1') == '1' ? 24 : 1;
1500
				$interval    = $last_update . " +" . $interval . " hours";
1501
				$next_update = new JDate($interval);
1502
				$next_update = $next_update->toSQL();
1503
1504
				if ($now >= $next_update)
1505
				{
1506
					$get_files = 1;
1507
				}
1508
				else
1509
				{
1510
					$get_files = 0;
1511
				}
1512
			}
1513
			else
1514
			{
1515
				$get_files = 1;
1516
			}
1517
1518
			if ($get_files == 0)
1519
			{
1520
				return false;
1521
			}
1522
1523
			$gh_paths                  = array();
1524
			$gh_client                 = $gh_data['github_client'];
1525
			$gh_user                   = 'joomla';
1526
			$gh_project                = 'joomla-cms';
1527
			$gh_branch                 = $params->get('gh_branch', 'master');
1528
			$gh_token                  = $params->get('gh_token', '');
1529
			$gh_paths['administrator'] = 'administrator/language/en-GB';
1530
			$gh_paths['site']          = 'language/en-GB';
1531
			$gh_paths['installation']  = 'installation/language/en-GB';
1532
1533
			$reference_client_path = JPATH_ROOT . '/' . $gh_paths[$gh_client];
1534
			$reference_client_path = JFolder::makeSafe($reference_client_path);
1535
1536
			$options = new JRegistry;
1537
1538 View Code Duplication
			if (!empty($gh_token))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1539
			{
1540
				$options->set('gh.token', $gh_token);
1541
				$github = new Github($options);
1542
			}
1543
			else
1544
			{
1545
				// Without a token runs fatal.
1546
				// $github = new JGithub;
1547
1548
				// Trying with a 'read only' public repositories token
1549
				// But base 64 encoded to avoid Github alarms sharing it.
1550
				$gh_token = base64_decode('MzY2NzYzM2ZkMzZmMWRkOGU5NmRiMTdjOGVjNTFiZTIyMzk4NzVmOA==');
1551
				$options->set('gh.token', $gh_token);
1552
				$github = new Github($options);
1553
			}
1554
1555
			try
1556
			{
1557
				$repostoryfiles = $github->repositories->contents->get(
1558
					$gh_user,
1559
					$gh_project,
1560
					$gh_paths[$gh_client],
1561
					$gh_branch
1562
					);
1563
			}
1564
			catch (Exception $e)
1565
			{
1566
				JFactory::getApplication()->enqueueMessage(
1567
					JText::_('COM_LOCALISE_ERROR_GITHUB_GETTING_REPOSITORY_FILES'),
1568
					'warning');
1569
1570
				return false;
1571
			}
1572
1573
			$all_files_list = self::getLanguagefileslist($develop_client_path);
1574
			$ini_files_list = self::getInifileslist($develop_client_path);
0 ignored issues
show
Unused Code introduced by
$ini_files_list is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1575
			$sha_files_list = self::getShafileslist($gh_data);
1576
1577
			$sha = '';
1578
			$files_to_include = array();
1579
1580
			foreach ($repostoryfiles as $repostoryfile)
1581
			{
1582
				$file_to_include     = $repostoryfile->name;
1583
				$file_path           = JFolder::makeSafe($develop_client_path . '/' . $file_to_include);
1584
				$reference_file_path = JFolder::makeSafe($reference_client_path . '/' . $file_to_include);
1585
1586
				if (	(array_key_exists($file_to_include, $sha_files_list)
1587
					&& ($sha_files_list[$file_to_include] != $repostoryfile->sha))
1588
					|| empty($sha_files_list)
1589
					|| !array_key_exists($file_to_include, $sha_files_list)
1590
					|| !JFile::exists($file_path))
1591
				{
1592
					$in_dev_file = $github->repositories->contents->get(
1593
							$gh_user,
1594
							$gh_project,
1595
							$repostoryfile->path,
1596
							$gh_branch
1597
							);
1598
				}
1599
				else
1600
				{
1601
					$in_dev_file = '';
1602
				}
1603
1604
				$files_to_include[] = $file_to_include;
1605
				$sha_path  = JPATH_COMPONENT_ADMINISTRATOR . '/develop/gh_joomla_' . $gh_client . '_files.txt';
1606
				$sha_path  = JFolder::makeSafe($sha_path);
1607
1608
				if (!empty($in_dev_file) && isset($in_dev_file->content))
1609
				{
1610
					$file_to_include = $repostoryfile->name;
1611
					$file_contents = base64_decode($in_dev_file->content);
1612
					JFile::write($file_path, $file_contents);
1613
1614
					if (!JFile::exists($file_path))
1615
					{
1616
						JFactory::getApplication()->enqueueMessage(
1617
							JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_CREATE_DEV_FILE'),
1618
							'warning');
1619
1620
						return false;
1621
					}
1622
1623
					if (!JFile::exists($reference_file_path)
1624
						&& ($gh_client == 'administrator' || $gh_client == 'site'))
1625
					{
1626
						// Adding files only present in develop to core reference location.
1627
						JFile::write($reference_file_path, $file_contents);
1628
1629
						if (!JFile::exists($reference_file_path))
1630
						{
1631
							JFactory::getApplication()->enqueueMessage(
1632
								JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_ADD_NEW_FILES'),
1633
								'warning');
1634
1635
							return false;
1636
						}
1637
1638
						JFactory::getApplication()->enqueueMessage(
1639
							JText::sprintf('COM_LOCALISE_NOTICE_GITHUB_FILE_ADDED', $file_to_include, $gh_branch, $gh_client),
1640
							'notice');
1641
					}
1642
				}
1643
1644
				// Saved for each time due few times get all the github files at same time can crash.
1645
				// This one can help to remember the last one saved correctly and next time continue from there.
1646
				$sha .= $repostoryfile->name . "::" . $repostoryfile->sha . "\n";
1647
				JFile::write($sha_path, $sha);
1648
1649
				if (!JFile::exists($sha_path))
1650
				{
1651
					JFactory::getApplication()->enqueueMessage(
1652
						JText::_('COM_LOCALISE_ERROR_GITHUB_NO_SHA_FILE_PRESENT'),
1653
						'warning');
1654
1655
					return false;
1656
				}
1657
			}
1658
1659
			if (!empty($all_files_list) && !empty($files_to_include))
1660
			{
1661
				// For files not present in dev yet.
1662
				$files_to_delete = array_diff($all_files_list, $files_to_include);
1663
1664
				if (!empty($files_to_delete))
1665
				{
1666
					foreach ($files_to_delete as $file_to_delete)
1667
					{
1668
						if ($file_to_delete != 'index.html')
1669
						{
1670
							$file_path = JFolder::makeSafe($develop_client_path . "/" . $file_to_delete);
1671
							JFile::delete($file_path);
1672
1673
							if (JFile::exists($file_path))
1674
							{
1675
								JFactory::getApplication()->enqueueMessage(
1676
									JText::sprintf('COM_LOCALISE_ERROR_GITHUB_FILE_TO_DELETE_IS_PRESENT', $file_to_delete),
1677
									'warning');
1678
1679
								return false;
1680
							}
1681
1682
							JFactory::getApplication()->enqueueMessage(
1683
								JText::sprintf('COM_LOCALISE_GITHUB_FILE_NOT_PRESENT_IN_DEV_YET', $file_to_delete),
1684
								'notice');
1685
						}
1686
					}
1687
				}
1688
			}
1689
1690
			if (!JFile::exists($xml_file))
1691
			{
1692
				JFactory::getApplication()->enqueueMessage(
1693
					JText::sprintf('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_GET_A_FULL_SET', $gh_branch),
1694
					'warning');
1695
1696
				return false;
1697
			}
1698
1699
			self::saveLastupdate($client_to_update);
1700
1701
			JFactory::getApplication()->enqueueMessage(
1702
				JText::sprintf('COM_LOCALISE_NOTICE_GITHUB_GETS_A_TARGET_FULL_SET', $gh_branch),
1703
				'notice');
1704
1705
			return true;
1706
		}
1707
1708
		JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_GITHUB_NO_DATA_PRESENT'), 'warning');
1709
1710
		return false;
1711
	}
1712
1713
	/**
1714
	 * Gets the changes between language files versions
1715
	 *
1716
	 * @param   array  $info              The data to catch grammar cases
1717
	 * @param   array  $refsections       The released reference data
1718
	 * @param   array  $develop_sections  The developed reference data
1719
	 *
1720
	 * @return  array
1721
	 *
1722
	 * @since   4.11
1723
	 */
1724
	public static function getDevelopchanges($info = array(), $refsections = array(), $develop_sections = array())
1725
	{
1726
		if (isset($refsections['keys']) && isset($develop_sections['keys']))
1727
		{
1728
			$istranslation     = $info['istranslation'];
1729
			$keys_in_reference = array_keys($refsections['keys']);
1730
			$keys_in_develop   = array_keys($develop_sections['keys']);
1731
1732
			// Catching new keys in develop
1733
			$developdata['extra_keys']['amount']  = 0;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$developdata was never initialized. Although not strictly required by PHP, it is generally a good practice to add $developdata = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1734
			$developdata['extra_keys']['keys']    = array();
1735
			$developdata['extra_keys']['strings'] = array();
1736
1737
			$extras_in_develop = array_diff($keys_in_develop, $keys_in_reference);
1738
1739
			if (!empty($extras_in_develop))
1740
			{
1741
				foreach ($extras_in_develop as $extra_key)
1742
				{
1743
					$developdata['extra_keys']['amount']++;
1744
					$developdata['extra_keys']['keys'][]              = $extra_key;
1745
					$developdata['extra_keys']['strings'][$extra_key] = $develop_sections['keys'][$extra_key];
1746
				}
1747
			}
1748
1749
			// Catching text changes in develop
1750
			$developdata['text_changes']['amount']     = 0;
1751
			$developdata['text_changes']['revised']    = 0;
1752
			$developdata['text_changes']['unrevised']  = 0;
1753
			$developdata['text_changes']['keys']       = array();
1754
			$developdata['text_changes']['ref_in_dev'] = array();
1755
			$developdata['text_changes']['ref']        = array();
1756
			$developdata['text_changes']['diff']       = array();
1757
1758
			foreach ($refsections['keys'] as $key => $string)
1759
			{
1760
				if (array_key_exists($key, $develop_sections['keys']))
1761
				{
1762
					$string_in_develop = $develop_sections['keys'][$key];
1763
					$text_changes = self::htmlgetTextchanges($string, $string_in_develop);
1764
1765
					if (!empty($text_changes))
1766
					{
1767
						if ($istranslation == 1)
1768
						{
1769
							$info['key']           = $key;
1770
							$info['source_text']   = $string;
1771
							$info['target_text']   = $string_in_develop;
1772
							$info['catch_grammar'] = 1;
1773
							$info['revised']       = 0;
1774
1775
							$grammar_case = self::searchRevisedvalue($info);
1776
						}
1777
						else
1778
						{
1779
							$grammar_case = '0';
1780
						}
1781
1782
						if ($grammar_case == '0')
1783
						{
1784
							$developdata['text_changes']['amount']++;
1785
							$developdata['text_changes']['keys'][]           = $key;
1786
							$developdata['text_changes']['ref_in_dev'][$key] = $develop_sections['keys'][$key];
1787
							$developdata['text_changes']['ref'][$key]        = $string;
1788
							$developdata['text_changes']['diff'][$key]       = $text_changes;
1789
						}
1790
					}
1791
				}
1792
			}
1793
1794
			return $developdata;
1795
		}
1796
1797
		return array();
1798
	}
1799
1800
	/**
1801
	 * Gets the develop path if exists
1802
	 *
1803
	 * @param   string  $client   The client
1804
	 * @param   string  $refpath  The data to the reference path
1805
	 *
1806
	 * @return  string
1807
	 *
1808
	 * @since   4.11
1809
	 */
1810
	public static function searchDevpath($client = '', $refpath = '')
1811
	{
1812
		$params             = JComponentHelper::getParams('com_localise');
1813
		$ref_tag            = $params->get('reference', 'en-GB');
1814
		$allow_develop      = $params->get('gh_allow_develop', 0);
1815
1816
		$develop_client_path = JPATH_ROOT
1817
					. '/media/com_localise/develop/github/joomla-cms/en-GB/'
1818
					. $client;
1819
1820
		$ref_file            = basename($refpath);
1821
		$develop_file_path   = JFolder::makeSafe("$develop_client_path/$ref_file");
1822
1823
		if (JFile::exists($develop_file_path) && $allow_develop == 1 && $ref_tag == 'en-GB')
1824
		{
1825
			$devpath = $develop_file_path;
1826
		}
1827
		else
1828
		{
1829
			$devpath = '';
1830
		}
1831
1832
		return $devpath;
1833
	}
1834
1835
	/**
1836
	 * Gets the customised source path if exists
1837
	 *
1838
	 * @param   string  $client   The client
1839
	 * @param   string  $refpath  The data to the reference path
1840
	 *
1841
	 * @return  string
1842
	 *
1843
	 * @since   4.11
1844
	 */
1845
	public static function searchCustompath($client = '', $refpath = '')
1846
	{
1847
		$params             = JComponentHelper::getParams('com_localise');
1848
		$ref_tag            = $params->get('reference', 'en-GB');
1849
		$allow_develop      = $params->get('gh_allow_develop', 0);
1850
		$customisedref      = $params->get('customisedref', '0');
1851
		$custom_client_path = JPATH_ROOT
1852
					. '/media/com_localise/customisedref/github/'
1853
					. $client
1854
					. '/'
1855
					. $customisedref;
1856
1857
		$ref_file         = basename($refpath);
1858
		$custom_file_path = JFolder::makeSafe("$custom_client_path/$ref_file");
1859
1860
		if (JFile::exists($custom_file_path) && $allow_develop == 1 && $ref_tag == 'en-GB' && $customisedref != 0)
1861
		{
1862
			$custom_path = $custom_file_path;
1863
		}
1864
		else
1865
		{
1866
			$custom_path = '';
1867
		}
1868
1869
		return $custom_path;
1870
	}
1871
1872
	/**
1873
	 * Allow combine the reference versions to obtain a right result editing in raw mode or saving source reference files
1874
	 * When development is enabled.
1875
	 *
1876
	 * @param   string  $refpath  The data to the reference path
1877
	 *
1878
	 * @param   string  $devpath  The data to the develop path
1879
	 *
1880
	 * @return  string
1881
	 *
1882
	 * @since   4.11
1883
	 */
1884
	public static function combineReferences($refpath = '', $devpath = '')
1885
	{
1886
		$params             = JComponentHelper::getParams('com_localise');
1887
		$ref_tag            = $params->get('reference', 'en-GB');
1888
		$allow_develop      = $params->get('gh_allow_develop', 0);
1889
		$combined_content   = '';
1890
1891
		if (JFile::exists($devpath) && JFile::exists($refpath) && $allow_develop == 1 && $ref_tag == 'en-GB')
1892
		{
1893
			$ref_sections      = self::parseSections($refpath);
1894
			$keys_in_reference = array_keys($ref_sections['keys']);
1895
1896
			$stream = new JStream;
1897
			$stream->open($devpath);
1898
			$stream->seek(0);
1899
1900
			while (!$stream->eof())
1901
			{
1902
				$line = $stream->gets();
1903
1904
				if (preg_match('/^([A-Z][A-Z0-9_\*\-\.]*)\s*=/', $line, $matches))
1905
				{
1906
					$key = $matches[1];
1907
1908
					if (in_array($key, $keys_in_reference))
1909
					{
1910
						$string = $ref_sections['keys'][$key];
1911
						$combined_content .= $key . '="' . str_replace('"', '"_QQ_"', $string) . "\"\n";
1912
					}
1913
					else
1914
					{
1915
						$combined_content .= $line;
1916
					}
1917
				}
1918
				else
1919
				{
1920
					$combined_content .= $line;
1921
				}
1922
			}
1923
1924
			$stream->close();
1925
		}
1926
1927
		return $combined_content;
1928
	}
1929
1930
	/**
1931
	 * Gets the list of ini files
1932
	 *
1933
	 * @param   string  $client_path  The data to the client path
1934
	 *
1935
	 * @return  array
1936
	 *
1937
	 * @since   4.11
1938
	 */
1939
	public static function getInifileslist($client_path = '')
1940
	{
1941
		if (!empty($client_path))
1942
		{
1943
			$files = JFolder::files($client_path, ".ini$");
1944
1945
			return $files;
1946
		}
1947
1948
	return array();
1949
	}
1950
1951
	/**
1952
	 * Gets the list of all type of files in develop
1953
	 *
1954
	 * @param   string  $develop_client_path  The data to the client path
1955
	 *
1956
	 * @return  array
1957
	 *
1958
	 * @since   4.11
1959
	 */
1960
	public static function getLanguagefileslist($develop_client_path = '')
1961
	{
1962
		if (!empty($develop_client_path))
1963
		{
1964
			$files = JFolder::files($develop_client_path);
1965
1966
			return $files;
1967
		}
1968
1969
	return array();
1970
	}
1971
1972
	/**
1973
	 * Gets the stored SHA id for the files in develop.
1974
	 *
1975
	 * @param   array  $gh_data  The required data.
1976
	 *
1977
	 * @return  array
1978
	 *
1979
	 * @since   4.11
1980
	 */
1981
	public static function getShafileslist($gh_data = array())
1982
	{
1983
		$sha_files = array();
1984
		$gh_client = $gh_data['github_client'];
1985
		$sha_path  = JFolder::makeSafe(JPATH_COMPONENT_ADMINISTRATOR . '/develop/gh_joomla_' . $gh_client . '_files.txt');
1986
1987
		if (JFile::exists($sha_path))
1988
		{
1989
			$file_contents = file_get_contents($sha_path);
1990
			$lines = preg_split("/\\r\\n|\\r|\\n/", $file_contents);
1991
1992
			if (!empty($lines))
1993
			{
1994
				foreach ($lines as $line)
1995
				{
1996
					if (!empty($line))
1997
					{
1998
						list($filename, $sha) = explode('::', $line, 2);
1999
2000
						if (!empty($filename) && !empty($sha))
2001
						{
2002
							$sha_files[$filename] = $sha;
2003
						}
2004
					}
2005
				}
2006
			}
2007
		}
2008
2009
	return $sha_files;
2010
	}
2011
2012
	/**
2013
	 * Save the date of the last Github files update by client.
2014
	 *
2015
	 * @param   string  $client_to_update  The client language files.
2016
	 *
2017
	 * @return  bolean
2018
	 *
2019
	 * @since   4.11
2020
	 */
2021
	public static function saveLastupdate($client_to_update)
2022
	{
2023
		$now    = new JDate;
2024
		$now    = $now->toSQL();
2025
		$params = JComponentHelper::getParams('com_localise');
2026
		$params->set($client_to_update, $now);
2027
2028
		$localise_id = JComponentHelper::getComponent('com_localise')->id;
2029
2030
		$table = JTable::getInstance('extension');
2031
		$table->load($localise_id);
2032
		$table->bind(array('params' => $params->toString()));
2033
2034
		if (!$table->check())
2035
		{
2036
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2037
2038
			return false;
2039
		}
2040
2041
		if (!$table->store())
2042
		{
2043
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2044
2045
			return false;
2046
		}
2047
2048
		return true;
2049
	}
2050
2051
	/**
2052
	 * Forces to save the customised source version to use. Option '0' returns to local installed instance.
2053
	 *
2054
	 * @param   string  $option  The option value to save.
2055
	 *
2056
	 * @return  bolean
2057
	 *
2058
	 * @since   4.11
2059
	 */
2060
	public static function setCustomisedsource($option = '0')
2061
	{
2062
		$params = JComponentHelper::getParams('com_localise');
2063
		$params->set('customisedref', $option);
2064
2065
		$localise_id = JComponentHelper::getComponent('com_localise')->id;
2066
2067
		$table = JTable::getInstance('extension');
2068
		$table->load($localise_id);
2069
		$table->bind(array('params' => $params->toString()));
2070
2071
		if (!$table->check())
2072
		{
2073
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2074
2075
			return false;
2076
		}
2077
2078
		if (!$table->store())
2079
		{
2080
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2081
2082
			return false;
2083
		}
2084
2085
		return true;
2086
	}
2087
2088
	/**
2089
	 * Load revised changes
2090
	 *
2091
	 * @param   array  $data  The required data.
2092
	 *
2093
	 * @return  array
2094
	 *
2095
	 * @since   4.11
2096
	 */
2097
	public static function searchRevisedvalue($data)
2098
	{
2099
		$client        = $data['client'];
2100
		$reftag        = $data['reftag'];
2101
		$tag           = $data['tag'];
2102
		$filename      = $data['filename'];
2103
		$revised       = $data['revised'];
2104
		$key           = $data['key'];
2105
		$target_text   = $data['target_text'];
2106
		$source_text   = $data['source_text'];
2107
		$istranslation = $data['istranslation'];
0 ignored issues
show
Unused Code introduced by
$istranslation is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2108
		$catch_grammar = $data['catch_grammar'];
2109
2110
		if (!empty($client) && !empty($reftag) && !empty($tag) && !empty($filename))
2111
		{
2112
			try
2113
			{
2114
				$db                 = JFactory::getDbo();
2115
				$query	            = $db->getQuery(true);
2116
2117
				$search_client      = $db->quote($client);
2118
				$search_reftag      = $db->quote($reftag);
2119
				$search_tag         = $db->quote($tag);
2120
				$search_filename    = $db->quote($filename);
2121
				$search_key         = $db->quote($key);
2122
				$search_target_text = $db->quote($target_text);
2123
				$search_source_text = $db->quote($source_text);
2124
2125
				$query->select(
2126
						array	(
2127
							$db->quoteName('revised')
2128
							)
2129
						);
2130
				$query->from(
2131
						$db->quoteName('#__localise_revised_values')
2132
						);
2133
				$query->where(
2134
						$db->quoteName('client') . '= ' . $search_client
2135
						);
2136
				$query->where(
2137
						$db->quoteName('reftag') . '= ' . $search_reftag
2138
2139
						);
2140
				$query->where(
2141
						$db->quoteName('tag') . '= ' . $search_tag
2142
2143
						);
2144
				$query->where(
2145
						$db->quoteName('filename') . '= ' . $search_filename
2146
						);
2147
				$query->where(
2148
						$db->quoteName('key') . '= ' . $search_key
2149
						);
2150
				$query->where(
2151
						$db->quoteName('target_text') . '= ' . $search_target_text
2152
						);
2153
				$query->where(
2154
						$db->quoteName('source_text') . '= ' . $search_source_text
2155
						);
2156
2157
				$db->setQuery($query);
2158
2159
					if (!$db->query())
2160
					{
2161
						throw new Exception($db->getErrorMsg());
2162
					}
2163
			}
2164
2165
			catch (JException $e)
0 ignored issues
show
Bug introduced by
The class JException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
2166
			{
2167
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_SEARCHING_REVISED_VALUES'), 'warning');
2168
2169
				return null;
2170
			}
2171
2172
			$result = $db->loadResult();
2173
2174
				if (!is_null($result))
2175
				{
2176
					return (int) $result;
2177
				}
2178
				elseif ($catch_grammar == '1')
2179
				{
2180
					return '0';
2181
				}
2182
				else
2183
				{
2184
					if (self::saveRevisedvalue($data))
2185
					{
2186
						return (int) $revised;
2187
					}
2188
					else
2189
					{
2190
						return null;
2191
					}
2192
				}
2193
		}
2194
2195
		return null;
2196
	}
2197
2198
	/**
2199
	 * Update revised changes
2200
	 *
2201
	 * @param   array  $data  The required data.
2202
	 *
2203
	 * @return  array
2204
	 *
2205
	 * @since   4.11
2206
	 */
2207
	public static function updateRevisedvalue($data)
2208
	{
2209
		$client      = $data['client'];
2210
		$reftag      = $data['reftag'];
2211
		$tag         = $data['tag'];
2212
		$filename    = $data['filename'];
2213
		$revised     = $data['revised'];
2214
		$key         = $data['key'];
2215
		$target_text = $data['target_text'];
2216
		$source_text = $data['source_text'];
2217
2218
		if (!empty($client) && !empty($reftag) && !empty($tag) && !empty($filename))
2219
		{
2220
			try
2221
			{
2222
				$db = JFactory::getDbo();
2223
2224
				$updated_client      = $db->quote($client);
2225
				$updated_reftag      = $db->quote($reftag);
2226
				$updated_tag         = $db->quote($tag);
2227
				$updated_filename    = $db->quote($filename);
2228
				$updated_revised     = $db->quote($revised);
2229
				$updated_key         = $db->quote($key);
2230
				$updated_target_text = $db->quote($target_text);
2231
				$updated_source_text = $db->quote($source_text);
2232
2233
				$query = $db->getQuery(true);
2234
2235
				$fields = array(
2236
					$db->quoteName('revised') . ' = ' . $updated_revised
2237
				);
2238
2239
				$conditions = array(
2240
					$db->quoteName('client') . ' = ' . $updated_client,
2241
					$db->quoteName('reftag') . ' = ' . $updated_reftag,
2242
					$db->quoteName('tag') . ' = ' . $updated_tag,
2243
					$db->quoteName('filename') . ' = ' . $updated_filename,
2244
					$db->quoteName('key') . ' = ' . $updated_key,
2245
					$db->quoteName('target_text') . ' = ' . $updated_target_text,
2246
					$db->quoteName('source_text') . ' = ' . $updated_source_text
2247
				);
2248
2249
				$query->update($db->quoteName('#__localise_revised_values'))->set($fields)->where($conditions);
2250
2251
				$db->setQuery($query);
2252
				$db->execute();
2253
			}
2254
2255
			catch (JException $e)
0 ignored issues
show
Bug introduced by
The class JException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
2256
			{
2257
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_UPDATING_REVISED_VALUES'), 'warning');
2258
2259
				return false;
2260
			}
2261
2262
			return true;
2263
		}
2264
2265
		return false;
2266
	}
2267
2268
	/**
2269
	 * Save revised changes
2270
	 *
2271
	 * @param   array  $data  The required data.
2272
	 *
2273
	 * @return  array
2274
	 *
2275
	 * @since   4.11
2276
	 */
2277
	public static function saveRevisedvalue($data)
2278
	{
2279
		$client      = $data['client'];
2280
		$reftag      = $data['reftag'];
2281
		$tag         = $data['tag'];
2282
		$filename    = $data['filename'];
2283
		$revised     = $data['revised'];
2284
		$key         = $data['key'];
2285
		$target_text = $data['target_text'];
2286
		$source_text = $data['source_text'];
2287
2288
		if (!empty($client) && !empty($reftag) && !empty($tag) && !empty($filename))
2289
		{
2290
			try
2291
			{
2292
				$db = JFactory::getDbo();
2293
2294
				$saved_client      = $db->quote($client);
2295
				$saved_reftag      = $db->quote($reftag);
2296
				$saved_tag         = $db->quote($tag);
2297
				$saved_filename    = $db->quote($filename);
2298
				$saved_revised     = $db->quote($revised);
2299
				$saved_key         = $db->quote($key);
2300
				$saved_target_text = $db->quote($target_text);
2301
				$saved_source_text = $db->quote($source_text);
2302
2303
				$query = $db->getQuery(true);
2304
2305
				$columns = array('client', 'reftag', 'tag', 'filename', 'revised', 'key', 'target_text', 'source_text');
2306
2307
				$values = array($saved_client, $saved_reftag, $saved_tag, $saved_filename, $saved_revised, $saved_key, $saved_target_text, $saved_source_text);
2308
2309
				$query
2310
					->insert($db->quoteName('#__localise_revised_values'))
2311
					->columns($db->quoteName($columns))
2312
					->values(implode(',', $values));
2313
2314
				$db->setQuery($query);
2315
				$db->execute();
2316
			}
2317
2318
			catch (JException $e)
0 ignored issues
show
Bug introduced by
The class JException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
2319
			{
2320
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_SAVING_REVISED_VALUES'), 'warning');
2321
2322
				return false;
2323
			}
2324
2325
			return true;
2326
		}
2327
2328
		return false;
2329
	}
2330
2331
	/**
2332
	 * Create the required folders for develop
2333
	 *
2334
	 * @param   array   $gh_data  Array with the data
2335
	 * @param   string  $index    If true, allow to create an index.html file
2336
	 *
2337
	 * @return  bolean
2338
	 *
2339
	 * @since   4.11
2340
	 */
2341
	public static function createFolder($gh_data = array(), $index = 'true')
2342
	{
2343
		$source_ref = $gh_data['customisedref'];
2344
2345
		if (!empty($gh_data) && isset($source_ref))
2346
		{
2347
		$full_path = JPATH_ROOT . '/media/com_localise/customisedref/github/'
2348
					. $gh_data['github_client']
2349
					. '/'
2350
					. $source_ref;
2351
2352
		$full_path = JFolder::makeSafe($full_path);
2353
2354
			if (!JFolder::create($full_path))
2355
			{
2356
			}
2357
2358
			if (JFolder::exists($full_path))
2359
			{
2360
				if ($index == 'true')
2361
				{
2362
				$cretate_index = self::createIndex($full_path);
2363
2364
					if ($cretate_index == 1)
2365
					{
2366
						return true;
2367
					}
2368
2369
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_CREATE_INDEX_FILE'), 'warning');
2370
2371
				return false;
2372
				}
2373
2374
			return true;
2375
			}
2376
			else
2377
			{
2378
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_CREATE_FOLDERS'), 'warning');
2379
2380
				return false;
2381
			}
2382
		}
2383
2384
	return false;
2385
	}
2386
2387
	/**
2388
	 * Creates an index.html file within folders for develop
2389
	 *
2390
	 * @param   string  $full_path  The full path.
2391
	 *
2392
	 * @return  bolean
2393
	 *
2394
	 * @since   4.11
2395
	 */
2396
	public static function createIndex($full_path = '')
2397
	{
2398
		if (!empty($full_path))
2399
		{
2400
		$path = JFolder::makeSafe($full_path . '/index.html');
2401
2402
		$index_content = '<!DOCTYPE html><title></title>';
2403
2404
			if (!JFile::exists($path))
2405
			{
2406
				JFile::write($path, $index_content);
2407
			}
2408
2409
			if (!JFile::exists($path))
2410
			{
2411
				return false;
2412
			}
2413
			else
2414
			{
2415
				return true;
2416
			}
2417
		}
2418
2419
	return false;
2420
	}
2421
2422
	/**
2423
	 * Gets the text changes.
2424
	 *
2425
	 * @param   array  $old  The string parts in reference.
2426
	 * @param   array  $new  The string parts in develop.
2427
	 *
2428
	 * @return  array
2429
	 *
2430
	 * @since   4.11
2431
	 */
2432
	public static function getTextchanges($old, $new)
2433
	{
2434
		$maxlen = 0;
2435
2436
		foreach ($old as $oindex => $ovalue)
2437
		{
2438
			$nkeys = array_keys($new, $ovalue);
2439
2440
			foreach ($nkeys as $nindex)
2441
			{
2442
				$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ? $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
0 ignored issues
show
Bug introduced by
The variable $matrix does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2443
2444
				if ($matrix[$oindex][$nindex] > $maxlen)
2445
				{
2446
					$maxlen = $matrix[$oindex][$nindex];
2447
					$omax = $oindex + 1 - $maxlen;
2448
					$nmax = $nindex + 1 - $maxlen;
2449
				}
2450
2451
			unset ($nkeys, $nindex);
2452
			}
2453
2454
		unset ($oindex, $ovalue);
2455
		}
2456
2457
		if ($maxlen == 0)
2458
		{
2459
			return array(array ('d' => $old, 'i' => $new));
2460
		}
2461
2462
		return array_merge(
2463
			self::getTextchanges(
2464
			array_slice($old, 0, $omax),
0 ignored issues
show
Bug introduced by
The variable $omax does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2465
			array_slice($new, 0, $nmax)
0 ignored issues
show
Bug introduced by
The variable $nmax does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2466
			),
2467
			array_slice($new, $nmax, $maxlen),
2468
			self::getTextchanges(
2469
			array_slice($old, $omax + $maxlen),
2470
			array_slice($new, $nmax + $maxlen)
2471
			)
2472
			);
2473
	}
2474
2475
	/**
2476
	 * Gets the html text changes.
2477
	 *
2478
	 * @param   string  $old  The string in reference.
2479
	 * @param   string  $new  The string in develop.
2480
	 *
2481
	 * @return  string
2482
	 *
2483
	 * @since   4.11
2484
	 */
2485
	public static function htmlgetTextchanges($old, $new)
2486
	{
2487
		$text_changes = '';
2488
2489
		if ($old == $new)
2490
		{
2491
			return $text_changes;
2492
		}
2493
2494
		$old = str_replace('  ', 'LOCALISEDOUBLESPACES', $old);
2495
		$new = str_replace('  ', 'LOCALISEDOUBLESPACES', $new);
2496
2497
		$diff = self::getTextchanges(explode(' ', $old), explode(' ', $new));
2498
2499
		foreach ($diff as $k)
2500
		{
2501
			if (is_array($k))
2502
			{
2503
				$text_changes .= (!empty ($k['d'])?"LOCALISEDELSTART"
2504
					. implode(' ', $k['d']) . "LOCALISEDELSTOP ":'')
2505
					. (!empty($k['i']) ? "LOCALISEINSSTART"
2506
					. implode(' ', $k['i'])
2507
					. "LOCALISEINSSTOP " : '');
2508
			}
2509
			else
2510
			{
2511
				$text_changes .= $k . ' ';
2512
			}
2513
2514
		unset ($k);
2515
		}
2516
2517
		$text_changes = htmlspecialchars($text_changes);
2518
		$text_changes = preg_replace('/LOCALISEINSSTART/', "<ins class='diff_ins'>", $text_changes);
2519
		$text_changes = preg_replace('/LOCALISEINSSTOP/', "</ins>", $text_changes);
2520
		$text_changes = preg_replace('/LOCALISEDELSTART/', "<del class='diff_del'>", $text_changes);
2521
		$text_changes = preg_replace('/LOCALISEDELSTOP/', "</del>", $text_changes);
2522
		$double_spaces = '<span class="red-space"><font color="red">XX</font></span>';
2523
		$text_changes = str_replace('LOCALISEDOUBLESPACES', $double_spaces, $text_changes);
2524
2525
	return $text_changes;
2526
	}
2527
}
2528