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.
Completed
Push — develop ( 7799bc...b8a19a )
by
unknown
13s
created

component/admin/helpers/localise.php (50 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
$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
$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
$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
$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
$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
$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
$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
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
$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
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
$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
$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
$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
$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
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
			// Allowed tricks.
1103
			// Configured to 0 the 2.5.x series are not allowed. Configured to 1 it is allowed.
1104
			$allow_25x = 1;
1105
1106
			foreach ($releases as $release)
1107
			{
1108
				$tag_name = $release->tag_name;
1109
				$tag_part = explode(".", $tag_name);
1110
				$undoted  = str_replace('.', '', $tag_name);
1111
				$excluded = 0;
1112
1113 View Code Duplication
				if ($tag_part[0] == '2' && $allow_25x == '0')
0 ignored issues
show
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...
1114
				{
1115
					$excluded = 1;
1116
				}
1117
				elseif ($tag_part[0] != '3' && $tag_part[0] != '2')
1118
				{
1119
					// Exclude platforms or similar stuff.
1120
					$excluded = 1;
1121
				}
1122
1123
				// Filtering also by "is_numeric" disable betas or similar releases.
1124 View Code Duplication
				if (!in_array($tag_name, $versions) && is_numeric($undoted) && $excluded == 0)
0 ignored issues
show
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...
1125
				{
1126
					$versions[] = $tag_name;
1127
					JFactory::getApplication()->enqueueMessage(
1128
						JText::sprintf('COM_LOCALISE_NOTICE_NEW_VERSION_DETECTED', $tag_name),
1129
						'notice');
1130
				}
1131
			}
1132
		}
1133
		catch (Exception $e)
1134
		{
1135
			JFactory::getApplication()->enqueueMessage(
1136
				JText::_('COM_LOCALISE_ERROR_GITHUB_GETTING_RELEASES'),
1137
				'warning');
1138
		}
1139
1140
		arsort($versions);
1141
1142
		$versions_file = '';
1143
1144
		foreach ($versions as $id => $version)
1145
		{
1146
			if (!empty($version))
1147
			{
1148
				$versions_file .= $version . "\n";
1149
			}
1150
		}
1151
1152
		JFile::write($versions_path, $versions_file);
1153
1154
		return $versions;
1155
	}
1156
1157
	/**
1158
	 * Save the last en-GB source version used as reference.
1159
	 *
1160
	 * @param   string  $client         The client
1161
	 *
1162
	 * @param   string  $customisedref  The version number
1163
	 *
1164
	 * @return  boolean
1165
	 *
1166
	 * @since   4.11
1167
	 */
1168
	public static function saveLastsourcereference($client = '', $customisedref = '')
1169
	{
1170
		$last_reference_file = JPATH_COMPONENT_ADMINISTRATOR
1171
					. '/customisedref/'
1172
					. $client
1173
					. '_last_source_ref.txt';
1174
1175
		$file_contents = $customisedref . "\n";
1176
1177
		if (!JFile::write($last_reference_file, $file_contents))
1178
		{
1179
			return false;
1180
		}
1181
1182
		return true;
1183
	}
1184
1185
	/**
1186
	 * Gets the last en-GB source reference version moved to the core folders.
1187
	 *
1188
	 * @return  array
1189
	 *
1190
	 * @since   4.11
1191
	 */
1192
	public static function getLastsourcereference()
1193
	{
1194
		$last_source_reference = array();
1195
		$last_source_reference['administrator'] = '';
1196
		$last_source_reference['site'] = '';
1197
		$last_source_reference['installation'] = '';
1198
1199
		$clients = array('administrator', 'site', 'installation');
1200
1201
		foreach ($clients as $client)
1202
		{
1203
			$last_reference_file = JPATH_COMPONENT_ADMINISTRATOR
1204
							. '/customisedref/'
1205
							. $client
1206
							. '_last_source_ref.txt';
1207
1208
			if (JFile::exists($last_reference_file))
1209
			{
1210
				$file_contents = file_get_contents($last_reference_file);
1211
				$lines = preg_split("/\\r\\n|\\r|\\n/", $file_contents);
1212
1213
				foreach ($lines as $line)
1214
				{
1215
					if (!empty($line))
1216
					{
1217
						$last_source_reference[$client] = $line;
1218
					}
1219
				}
1220
			}
1221
		}
1222
1223
		return $last_source_reference;
1224
	}
1225
1226
	/**
1227
	 * Gets the reference name to use at Github
1228
	 *
1229
	 * @param   array  $gh_data  Array with the required data
1230
	 *
1231
	 * @return  array
1232
	 *
1233
	 * @since   4.11
1234
	 */
1235
	public static function getCustomisedsource($gh_data = array())
1236
	{
1237
		$source_ref        = $gh_data['customisedref'];
1238
		$allow_develop     = $gh_data['allow_develop'];
0 ignored issues
show
$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...
1239
1240
		$sources = array();
1241
1242
		// Detailing it we can handle exceptions and add other Github users or projects.
1243
		// To get the language files for a determined Joomla's version that is not present from main Github repository.
1244
		$sources['3.4.1']['user']    = 'joomla';
1245
		$sources['3.4.1']['project'] = 'joomla-cms';
1246
		$sources['3.4.1']['branch']  = '3.4.1';
1247
1248
		if (array_key_exists($source_ref, $sources))
1249
		{
1250
			return ($sources[$source_ref]);
1251
		}
1252
1253
		// For undefined REF 0 or unlisted cases due Joomla releases at Github are following a version name patern.
1254
		$sources[$source_ref]['user']    = 'joomla';
1255
		$sources[$source_ref]['project'] = 'joomla-cms';
1256
		$sources[$source_ref]['branch']  = $source_ref;
1257
1258
	return ($sources[$source_ref]);
1259
	}
1260
1261
	/**
1262
	 * Keep updated the customised client path including only the common files present in develop.
1263
	 *
1264
	 * @param   string  $client              The client
1265
	 *
1266
	 * @param   string  $custom_client_path  The path where the new source reference is stored
1267
	 *
1268
	 * @return  boolean
1269
	 *
1270
	 * @since   4.11
1271
	 */
1272
	public static function updateSourcereference($client, $custom_client_path)
1273
	{
1274
		$develop_client_path   = JPATH_ROOT . '/media/com_localise/develop/github/joomla-cms/en-GB/' . $client;
1275
		$develop_client_path   = JFolder::makeSafe($develop_client_path);
1276
1277
		$custom_ini_files_list = self::getInifileslist($custom_client_path);
1278
		$last_ini_files_list   = self::getInifileslist($develop_client_path);
1279
1280
		$files_to_exclude = array();
0 ignored issues
show
$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...
1281
1282 View Code Duplication
		if (!JFile::exists($develop_client_path . '/en-GB.xml'))
0 ignored issues
show
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...
1283
		{
1284
			JFactory::getApplication()->enqueueMessage(
1285
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_TARGET_FILES'),
1286
				'warning');
1287
1288
			return false;
1289
		}
1290
		elseif (!JFile::exists($custom_client_path . '/en-GB.xml'))
1291
		{
1292
			JFactory::getApplication()->enqueueMessage(
1293
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_SOURCE_FILES'),
1294
				'warning');
1295
1296
			return false;
1297
		}
1298
1299
		// This one is for files not present within last in dev yet.
1300
		// Due have no sense add old language files to translate or revise for the comming soon package.
1301
1302
		$files_to_exclude = array_diff($custom_ini_files_list, $last_ini_files_list);
1303
1304
		if (!empty($files_to_exclude))
1305
		{
1306
			$errors = 0;
1307
1308
			foreach ($files_to_exclude as $file_to_delete)
1309
			{
1310
				$custom_file_path = JFolder::makeSafe($custom_client_path . "/" . $file_to_delete);
1311
1312
				if (!JFile::delete($custom_file_path))
1313
				{
1314
					$errors++;
1315
				}
1316
			}
1317
1318
			if ($errors > 0)
1319
			{
1320
				JFactory::getApplication()->enqueueMessage(
1321
					JText::sprintf('COM_LOCALISE_ERROR_DELETING_EXTRA_SOURCE_FILES', $errors),
1322
					'warning');
1323
1324
				return false;
1325
			}
1326
		}
1327
1328
		return true;
1329
	}
1330
1331
	/**
1332
	 * Keep updated the core path with the selected source files as reference (used at previous working mode).
1333
	 *
1334
	 * @param   string  $client                 The client
1335
	 *
1336
	 * @param   string  $custom_client_path     The path where the new source reference is stored
1337
	 *
1338
	 * @param   string  $reference_client_path  The path where the old source reference is stored
1339
	 *
1340
	 * @return  boolean
1341
	 *
1342
	 * @since   4.11
1343
	 */
1344
	public static function updateSourcereferencedirectly($client, $custom_client_path, $reference_client_path)
1345
	{
1346
		$develop_client_path   = JPATH_ROOT . '/media/com_localise/develop/github/joomla-cms/en-GB/' . $client;
1347
		$develop_client_path   = JFolder::makeSafe($develop_client_path);
1348
1349
		$custom_ini_files_list = self::getInifileslist($custom_client_path);
1350
		$last_ini_files_list   = self::getInifileslist($develop_client_path);
1351
1352
		$files_to_exclude = array();
0 ignored issues
show
$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...
1353
1354 View Code Duplication
		if (!JFile::exists($develop_client_path . '/en-GB.xml'))
0 ignored issues
show
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...
1355
		{
1356
			JFactory::getApplication()->enqueueMessage(
1357
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_TARGET_FILES'),
1358
				'warning');
1359
1360
			return false;
1361
		}
1362
		elseif (!JFile::exists($custom_client_path . '/en-GB.xml'))
1363
		{
1364
			JFactory::getApplication()->enqueueMessage(
1365
				JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_UPDATE_SOURCE_FILES'),
1366
				'warning');
1367
1368
			return false;
1369
		}
1370
1371
		// This one is for core files not present within last in dev yet.
1372
		// Due have no sense add old language files to translate for the comming soon package.
1373
1374
		$files_to_exclude = array_diff($custom_ini_files_list, $last_ini_files_list);
1375
1376
		if (!empty($files_to_exclude))
1377
		{
1378
			foreach ($files_to_exclude as $file_to_delete)
1379
			{
1380
				$custom_file_path = JFolder::makeSafe($custom_client_path . "/" . $file_to_delete);
1381
				$actual_file_path = JFolder::makeSafe($reference_client_path . "/" . $file_to_delete);
1382
1383
				JFile::delete($custom_file_path);
1384
1385
				// Also verify if the same file is also present in core language folder.
1386
1387
				if (JFile::exists($actual_file_path))
1388
				{
1389
					JFile::delete($actual_file_path);
1390
1391
					JFactory::getApplication()->enqueueMessage(
1392
					JText::sprintf('COM_LOCALISE_OLD_FILE_DELETED', $file_to_delete),
1393
					'notice');
1394
				}
1395
			}
1396
1397
			// Getting the new list again
1398
			$custom_ini_files_list = self::getInifileslist($custom_client_path);
1399
		}
1400
1401
		$errors = 0;
1402
1403
		foreach ($custom_ini_files_list as $customised_source_file)
1404
		{
1405
			$source_path = $custom_client_path . '/' . $customised_source_file;
1406
			$file_contents = file_get_contents($source_path);
1407
			$target_path = $reference_client_path . '/' . $customised_source_file;
1408
1409
			if (!JFile::write($target_path, $file_contents))
1410
			{
1411
				$errors++;
1412
			}
1413
		}
1414
1415
		if ($errors > 0)
1416
		{
1417
			JFactory::getApplication()->enqueueMessage(
1418
				JText::sprintf('COM_LOCALISE_ERROR_SAVING_FILES_AT_CORE_FOLDER', $errors),
1419
				'warning');
1420
1421
			return false;
1422
		}
1423
1424
		return true;
1425
	}
1426
1427
	/**
1428
	 * Gets from zero or keept updated the files in develop to use as target reference from Github
1429
	 *
1430
	 * @param   array  $gh_data  Array with the required data
1431
	 *
1432
	 * @return  array
1433
	 *
1434
	 * @since   4.11
1435
	 */
1436
	public static function getTargetgithubfiles($gh_data = array())
1437
	{
1438
		if (!empty($gh_data))
1439
		{
1440
			$now                = new JDate;
1441
			$now                = $now->toSQL();
1442
			$params             = JComponentHelper::getParams('com_localise');
1443
			$client_to_update   = 'gh_' . $gh_data['github_client'] . '_last_update';
1444
			$last_stored_update = $params->get($client_to_update, '');
1445
			$ref_tag            = $params->get('reference', 'en-GB');
1446
			$allow_develop      = $params->get('gh_allow_develop', 0);
1447
1448
			if ($allow_develop == 0)
1449
			{
1450
				return false;
1451
			}
1452
1453
			if ($ref_tag != 'en-GB')
1454
			{
1455
				JFactory::getApplication()->enqueueMessage(
1456
					JText::_('COM_LOCALISE_ERROR_GETTING_ALLOWED_REFERENCE_TAG'),
1457
					'warning');
1458
1459
				return false;
1460
			}
1461
1462
			$develop_client_path = JPATH_ROOT
1463
						. '/media/com_localise/develop/github/joomla-cms/en-GB/'
1464
						. $gh_data['github_client'];
1465
1466
			$develop_client_path = JFolder::makeSafe($develop_client_path);
1467
			$xml_file            = $develop_client_path . '/en-GB.xml';
1468
1469
			if (!JFile::exists($xml_file))
1470
			{
1471
				$get_files = 1;
1472
			}
1473
			elseif (!empty($last_stored_update))
1474
			{
1475
				$last_update = new JDate($last_stored_update);
1476
				$last_update = $last_update->toSQL();
1477
				$interval    = $params->get('gh_updates_interval', '1') == '1' ? 24 : 1;
1478
				$interval    = $last_update . " +" . $interval . " hours";
1479
				$next_update = new JDate($interval);
1480
				$next_update = $next_update->toSQL();
1481
1482
				if ($now >= $next_update)
1483
				{
1484
					$get_files = 1;
1485
				}
1486
				else
1487
				{
1488
					$get_files = 0;
1489
				}
1490
			}
1491
			else
1492
			{
1493
				$get_files = 1;
1494
			}
1495
1496
			if ($get_files == 0)
1497
			{
1498
				return false;
1499
			}
1500
1501
			$gh_paths                  = array();
1502
			$gh_client                 = $gh_data['github_client'];
1503
			$gh_user                   = 'joomla';
1504
			$gh_project                = 'joomla-cms';
1505
			$gh_branch                 = $params->get('gh_branch', 'master');
1506
			$gh_token                  = $params->get('gh_token', '');
1507
			$gh_paths['administrator'] = 'administrator/language/en-GB';
1508
			$gh_paths['site']          = 'language/en-GB';
1509
			$gh_paths['installation']  = 'installation/language/en-GB';
1510
1511
			$reference_client_path = JPATH_ROOT . '/' . $gh_paths[$gh_client];
1512
			$reference_client_path = JFolder::makeSafe($reference_client_path);
1513
1514
			$options = new JRegistry;
1515
1516 View Code Duplication
			if (!empty($gh_token))
0 ignored issues
show
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...
1517
			{
1518
				$options->set('gh.token', $gh_token);
1519
				$github = new Github($options);
1520
			}
1521
			else
1522
			{
1523
				// Without a token runs fatal.
1524
				// $github = new JGithub;
1525
1526
				// Trying with a 'read only' public repositories token
1527
				// But base 64 encoded to avoid Github alarms sharing it.
1528
				$gh_token = base64_decode('MzY2NzYzM2ZkMzZmMWRkOGU5NmRiMTdjOGVjNTFiZTIyMzk4NzVmOA==');
1529
				$options->set('gh.token', $gh_token);
1530
				$github = new Github($options);
1531
			}
1532
1533
			try
1534
			{
1535
				$repostoryfiles = $github->repositories->contents->get(
1536
					$gh_user,
1537
					$gh_project,
1538
					$gh_paths[$gh_client],
1539
					$gh_branch
1540
					);
1541
			}
1542
			catch (Exception $e)
1543
			{
1544
				JFactory::getApplication()->enqueueMessage(
1545
					JText::_('COM_LOCALISE_ERROR_GITHUB_GETTING_REPOSITORY_FILES'),
1546
					'warning');
1547
1548
				return false;
1549
			}
1550
1551
			$all_files_list = self::getLanguagefileslist($develop_client_path);
1552
			$ini_files_list = self::getInifileslist($develop_client_path);
0 ignored issues
show
$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...
1553
			$sha_files_list = self::getShafileslist($gh_data);
1554
1555
			$sha = '';
1556
			$files_to_include = array();
1557
1558
			foreach ($repostoryfiles as $repostoryfile)
1559
			{
1560
				$file_to_include     = $repostoryfile->name;
1561
				$file_path           = JFolder::makeSafe($develop_client_path . '/' . $file_to_include);
1562
				$reference_file_path = JFolder::makeSafe($reference_client_path . '/' . $file_to_include);
1563
1564
				if (	(array_key_exists($file_to_include, $sha_files_list)
1565
					&& ($sha_files_list[$file_to_include] != $repostoryfile->sha))
1566
					|| empty($sha_files_list)
1567
					|| !array_key_exists($file_to_include, $sha_files_list)
1568
					|| !JFile::exists($file_path))
1569
				{
1570
					$in_dev_file = $github->repositories->contents->get(
1571
							$gh_user,
1572
							$gh_project,
1573
							$repostoryfile->path,
1574
							$gh_branch
1575
							);
1576
				}
1577
				else
1578
				{
1579
					$in_dev_file = '';
1580
				}
1581
1582
				$files_to_include[] = $file_to_include;
1583
				$sha_path  = JPATH_COMPONENT_ADMINISTRATOR . '/develop/gh_joomla_' . $gh_client . '_files.txt';
1584
				$sha_path  = JFolder::makeSafe($sha_path);
1585
1586
				if (!empty($in_dev_file) && isset($in_dev_file->content))
1587
				{
1588
					$file_to_include = $repostoryfile->name;
1589
					$file_contents = base64_decode($in_dev_file->content);
1590
					JFile::write($file_path, $file_contents);
1591
1592
					if (!JFile::exists($file_path))
1593
					{
1594
						JFactory::getApplication()->enqueueMessage(
1595
							JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_CREATE_DEV_FILE'),
1596
							'warning');
1597
1598
						return false;
1599
					}
1600
1601
					if (!JFile::exists($reference_file_path)
1602
						&& ($gh_client == 'administrator' || $gh_client == 'site'))
1603
					{
1604
						// Adding files only present in develop to core reference location.
1605
						JFile::write($reference_file_path, $file_contents);
1606
1607
						if (!JFile::exists($reference_file_path))
1608
						{
1609
							JFactory::getApplication()->enqueueMessage(
1610
								JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_ADD_NEW_FILES'),
1611
								'warning');
1612
1613
							return false;
1614
						}
1615
1616
						JFactory::getApplication()->enqueueMessage(
1617
							JText::sprintf('COM_LOCALISE_NOTICE_GITHUB_FILE_ADDED', $file_to_include, $gh_branch, $gh_client),
1618
							'notice');
1619
					}
1620
				}
1621
1622
				// Saved for each time due few times get all the github files at same time can crash.
1623
				// This one can help to remember the last one saved correctly and next time continue from there.
1624
				$sha .= $repostoryfile->name . "::" . $repostoryfile->sha . "\n";
1625
				JFile::write($sha_path, $sha);
1626
1627
				if (!JFile::exists($sha_path))
1628
				{
1629
					JFactory::getApplication()->enqueueMessage(
1630
						JText::_('COM_LOCALISE_ERROR_GITHUB_NO_SHA_FILE_PRESENT'),
1631
						'warning');
1632
1633
					return false;
1634
				}
1635
			}
1636
1637
			if (!empty($all_files_list) && !empty($files_to_include))
1638
			{
1639
				// For files not present in dev yet.
1640
				$files_to_delete = array_diff($all_files_list, $files_to_include);
1641
1642
				if (!empty($files_to_delete))
1643
				{
1644
					foreach ($files_to_delete as $file_to_delete)
1645
					{
1646
						if ($file_to_delete != 'index.html')
1647
						{
1648
							$file_path = JFolder::makeSafe($develop_client_path . "/" . $file_to_delete);
1649
							JFile::delete($file_path);
1650
1651
							if (JFile::exists($file_path))
1652
							{
1653
								JFactory::getApplication()->enqueueMessage(
1654
									JText::sprintf('COM_LOCALISE_ERROR_GITHUB_FILE_TO_DELETE_IS_PRESENT', $file_to_delete),
1655
									'warning');
1656
1657
								return false;
1658
							}
1659
1660
							JFactory::getApplication()->enqueueMessage(
1661
								JText::sprintf('COM_LOCALISE_GITHUB_FILE_NOT_PRESENT_IN_DEV_YET', $file_to_delete),
1662
								'notice');
1663
						}
1664
					}
1665
				}
1666
			}
1667
1668
			if (!JFile::exists($xml_file))
1669
			{
1670
				JFactory::getApplication()->enqueueMessage(
1671
					JText::sprintf('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_GET_A_FULL_SET', $gh_branch),
1672
					'warning');
1673
1674
				return false;
1675
			}
1676
1677
			self::saveLastupdate($client_to_update);
1678
1679
			JFactory::getApplication()->enqueueMessage(
1680
				JText::sprintf('COM_LOCALISE_NOTICE_GITHUB_GETS_A_TARGET_FULL_SET', $gh_branch),
1681
				'notice');
1682
1683
			return true;
1684
		}
1685
1686
		JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_GITHUB_NO_DATA_PRESENT'), 'warning');
1687
1688
		return false;
1689
	}
1690
1691
	/**
1692
	 * Gets the changes between language files versions
1693
	 *
1694
	 * @param   array  $info              The data to catch grammar cases
1695
	 * @param   array  $refsections       The released reference data
1696
	 * @param   array  $develop_sections  The developed reference data
1697
	 *
1698
	 * @return  array
1699
	 *
1700
	 * @since   4.11
1701
	 */
1702
	public static function getDevelopchanges($info = array(), $refsections = array(), $develop_sections = array())
1703
	{
1704
		if (isset($refsections['keys']) && isset($develop_sections['keys']))
1705
		{
1706
			$istranslation     = $info['istranslation'];
1707
			$keys_in_reference = array_keys($refsections['keys']);
1708
			$keys_in_develop   = array_keys($develop_sections['keys']);
1709
1710
			// Catching new keys in develop
1711
			$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...
1712
			$developdata['extra_keys']['keys']    = array();
1713
			$developdata['extra_keys']['strings'] = array();
1714
1715
			$extras_in_develop = array_diff($keys_in_develop, $keys_in_reference);
1716
1717
			if (!empty($extras_in_develop))
1718
			{
1719
				foreach ($extras_in_develop as $extra_key)
1720
				{
1721
					$developdata['extra_keys']['amount']++;
1722
					$developdata['extra_keys']['keys'][]              = $extra_key;
1723
					$developdata['extra_keys']['strings'][$extra_key] = $develop_sections['keys'][$extra_key];
1724
				}
1725
			}
1726
1727
			// Catching text changes in develop
1728
			$developdata['text_changes']['amount']     = 0;
1729
			$developdata['text_changes']['revised']    = 0;
1730
			$developdata['text_changes']['unrevised']  = 0;
1731
			$developdata['text_changes']['keys']       = array();
1732
			$developdata['text_changes']['ref_in_dev'] = array();
1733
			$developdata['text_changes']['ref']        = array();
1734
			$developdata['text_changes']['diff']       = array();
1735
1736
			foreach ($refsections['keys'] as $key => $string)
1737
			{
1738
				if (array_key_exists($key, $develop_sections['keys']))
1739
				{
1740
					$string_in_develop = $develop_sections['keys'][$key];
1741
					$text_changes = self::htmlgetTextchanges($string, $string_in_develop);
1742
1743
					if (!empty($text_changes))
1744
					{
1745
						if ($istranslation == 1)
1746
						{
1747
							$info['key']           = $key;
1748
							$info['source_text']   = $string;
1749
							$info['target_text']   = $string_in_develop;
1750
							$info['catch_grammar'] = 1;
1751
							$info['revised']       = 0;
1752
1753
							$grammar_case = self::searchRevisedvalue($info);
1754
						}
1755
						else
1756
						{
1757
							$grammar_case = '0';
1758
						}
1759
1760
						if ($grammar_case == '0')
1761
						{
1762
							$developdata['text_changes']['amount']++;
1763
							$developdata['text_changes']['keys'][]           = $key;
1764
							$developdata['text_changes']['ref_in_dev'][$key] = $develop_sections['keys'][$key];
1765
							$developdata['text_changes']['ref'][$key]        = $string;
1766
							$developdata['text_changes']['diff'][$key]       = $text_changes;
1767
						}
1768
					}
1769
				}
1770
			}
1771
1772
			return $developdata;
1773
		}
1774
1775
		return array();
1776
	}
1777
1778
	/**
1779
	 * Gets the develop path if exists
1780
	 *
1781
	 * @param   string  $client   The client
1782
	 * @param   string  $refpath  The data to the reference path
1783
	 *
1784
	 * @return  string
1785
	 *
1786
	 * @since   4.11
1787
	 */
1788
	public static function searchDevpath($client = '', $refpath = '')
1789
	{
1790
		$params             = JComponentHelper::getParams('com_localise');
1791
		$ref_tag            = $params->get('reference', 'en-GB');
1792
		$allow_develop      = $params->get('gh_allow_develop', 0);
1793
1794
		$develop_client_path = JPATH_ROOT
1795
					. '/media/com_localise/develop/github/joomla-cms/en-GB/'
1796
					. $client;
1797
1798
		$ref_file            = basename($refpath);
1799
		$develop_file_path   = JFolder::makeSafe("$develop_client_path/$ref_file");
1800
1801
		if (JFile::exists($develop_file_path) && $allow_develop == 1 && $ref_tag == 'en-GB')
1802
		{
1803
			$devpath = $develop_file_path;
1804
		}
1805
		else
1806
		{
1807
			$devpath = '';
1808
		}
1809
1810
		return $devpath;
1811
	}
1812
1813
	/**
1814
	 * Gets the customised source path if exists
1815
	 *
1816
	 * @param   string  $client   The client
1817
	 * @param   string  $refpath  The data to the reference path
1818
	 *
1819
	 * @return  string
1820
	 *
1821
	 * @since   4.11
1822
	 */
1823
	public static function searchCustompath($client = '', $refpath = '')
1824
	{
1825
		$params             = JComponentHelper::getParams('com_localise');
1826
		$ref_tag            = $params->get('reference', 'en-GB');
1827
		$allow_develop      = $params->get('gh_allow_develop', 0);
1828
		$customisedref      = $params->get('customisedref', '0');
1829
		$custom_client_path = JPATH_ROOT
1830
					. '/media/com_localise/customisedref/github/'
1831
					. $client
1832
					. '/'
1833
					. $customisedref;
1834
1835
		$ref_file         = basename($refpath);
1836
		$custom_file_path = JFolder::makeSafe("$custom_client_path/$ref_file");
1837
1838
		if (JFile::exists($custom_file_path) && $allow_develop == 1 && $ref_tag == 'en-GB' && $customisedref != 0)
1839
		{
1840
			$custom_path = $custom_file_path;
1841
		}
1842
		else
1843
		{
1844
			$custom_path = '';
1845
		}
1846
1847
		return $custom_path;
1848
	}
1849
1850
	/**
1851
	 * Allow combine the reference versions to obtain a right result editing in raw mode or saving source reference files
1852
	 * When development is enabled.
1853
	 *
1854
	 * @param   string  $refpath  The data to the reference path
1855
	 *
1856
	 * @param   string  $devpath  The data to the develop path
1857
	 *
1858
	 * @return  string
1859
	 *
1860
	 * @since   4.11
1861
	 */
1862
	public static function combineReferences($refpath = '', $devpath = '')
1863
	{
1864
		$params             = JComponentHelper::getParams('com_localise');
1865
		$ref_tag            = $params->get('reference', 'en-GB');
1866
		$allow_develop      = $params->get('gh_allow_develop', 0);
1867
		$combined_content   = '';
1868
1869
		if (JFile::exists($devpath) && JFile::exists($refpath) && $allow_develop == 1 && $ref_tag == 'en-GB')
1870
		{
1871
			$ref_sections      = self::parseSections($refpath);
1872
			$keys_in_reference = array_keys($ref_sections['keys']);
1873
1874
			$stream = new JStream;
1875
			$stream->open($devpath);
1876
			$stream->seek(0);
1877
1878
			while (!$stream->eof())
1879
			{
1880
				$line = $stream->gets();
1881
1882
				if (preg_match('/^([A-Z][A-Z0-9_\*\-\.]*)\s*=/', $line, $matches))
1883
				{
1884
					$key = $matches[1];
1885
1886
					if (in_array($key, $keys_in_reference))
1887
					{
1888
						$string = $ref_sections['keys'][$key];
1889
						$combined_content .= $key . '="' . str_replace('"', '"_QQ_"', $string) . "\"\n";
1890
					}
1891
					else
1892
					{
1893
						$combined_content .= $line;
1894
					}
1895
				}
1896
				else
1897
				{
1898
					$combined_content .= $line;
1899
				}
1900
			}
1901
1902
			$stream->close();
1903
		}
1904
1905
		return $combined_content;
1906
	}
1907
1908
	/**
1909
	 * Gets the list of ini files
1910
	 *
1911
	 * @param   string  $client_path  The data to the client path
1912
	 *
1913
	 * @return  array
1914
	 *
1915
	 * @since   4.11
1916
	 */
1917
	public static function getInifileslist($client_path = '')
1918
	{
1919
		if (!empty($client_path))
1920
		{
1921
			$files = JFolder::files($client_path, ".ini$");
1922
1923
			return $files;
1924
		}
1925
1926
	return array();
1927
	}
1928
1929
	/**
1930
	 * Gets the list of all type of files in develop
1931
	 *
1932
	 * @param   string  $develop_client_path  The data to the client path
1933
	 *
1934
	 * @return  array
1935
	 *
1936
	 * @since   4.11
1937
	 */
1938
	public static function getLanguagefileslist($develop_client_path = '')
1939
	{
1940
		if (!empty($develop_client_path))
1941
		{
1942
			$files = JFolder::files($develop_client_path);
1943
1944
			return $files;
1945
		}
1946
1947
	return array();
1948
	}
1949
1950
	/**
1951
	 * Gets the stored SHA id for the files in develop.
1952
	 *
1953
	 * @param   array  $gh_data  The required data.
1954
	 *
1955
	 * @return  array
1956
	 *
1957
	 * @since   4.11
1958
	 */
1959
	public static function getShafileslist($gh_data = array())
1960
	{
1961
		$sha_files = array();
1962
		$gh_client = $gh_data['github_client'];
1963
		$sha_path  = JFolder::makeSafe(JPATH_COMPONENT_ADMINISTRATOR . '/develop/gh_joomla_' . $gh_client . '_files.txt');
1964
1965
		if (JFile::exists($sha_path))
1966
		{
1967
			$file_contents = file_get_contents($sha_path);
1968
			$lines = preg_split("/\\r\\n|\\r|\\n/", $file_contents);
1969
1970
			if (!empty($lines))
1971
			{
1972
				foreach ($lines as $line)
1973
				{
1974
					if (!empty($line))
1975
					{
1976
						list($filename, $sha) = explode('::', $line, 2);
1977
1978
						if (!empty($filename) && !empty($sha))
1979
						{
1980
							$sha_files[$filename] = $sha;
1981
						}
1982
					}
1983
				}
1984
			}
1985
		}
1986
1987
	return $sha_files;
1988
	}
1989
1990
	/**
1991
	 * Save the date of the last Github files update by client.
1992
	 *
1993
	 * @param   string  $client_to_update  The client language files.
1994
	 *
1995
	 * @return  bolean
1996
	 *
1997
	 * @since   4.11
1998
	 */
1999
	public static function saveLastupdate($client_to_update)
2000
	{
2001
		$now    = new JDate;
2002
		$now    = $now->toSQL();
2003
		$params = JComponentHelper::getParams('com_localise');
2004
		$params->set($client_to_update, $now);
2005
2006
		$localise_id = JComponentHelper::getComponent('com_localise')->id;
2007
2008
		$table = JTable::getInstance('extension');
2009
		$table->load($localise_id);
2010
		$table->bind(array('params' => $params->toString()));
2011
2012
		if (!$table->check())
2013
		{
2014
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2015
2016
			return false;
2017
		}
2018
2019
		if (!$table->store())
2020
		{
2021
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2022
2023
			return false;
2024
		}
2025
2026
		return true;
2027
	}
2028
2029
	/**
2030
	 * Forces to save the customised source version to use. Option '0' returns to local installed instance.
2031
	 *
2032
	 * @param   string  $option  The option value to save.
2033
	 *
2034
	 * @return  bolean
2035
	 *
2036
	 * @since   4.11
2037
	 */
2038
	public static function setCustomisedsource($option = '0')
2039
	{
2040
		$params = JComponentHelper::getParams('com_localise');
2041
		$params->set('customisedref', $option);
2042
2043
		$localise_id = JComponentHelper::getComponent('com_localise')->id;
2044
2045
		$table = JTable::getInstance('extension');
2046
		$table->load($localise_id);
2047
		$table->bind(array('params' => $params->toString()));
2048
2049
		if (!$table->check())
2050
		{
2051
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2052
2053
			return false;
2054
		}
2055
2056
		if (!$table->store())
2057
		{
2058
			JFactory::getApplication()->enqueueMessage($table->getError(), 'warning');
2059
2060
			return false;
2061
		}
2062
2063
		return true;
2064
	}
2065
2066
	/**
2067
	 * Load revised changes
2068
	 *
2069
	 * @param   array  $data  The required data.
2070
	 *
2071
	 * @return  array
2072
	 *
2073
	 * @since   4.11
2074
	 */
2075
	public static function searchRevisedvalue($data)
2076
	{
2077
		$client        = $data['client'];
2078
		$reftag        = $data['reftag'];
2079
		$tag           = $data['tag'];
2080
		$filename      = $data['filename'];
2081
		$revised       = $data['revised'];
2082
		$key           = $data['key'];
2083
		$target_text   = $data['target_text'];
2084
		$source_text   = $data['source_text'];
2085
		$istranslation = $data['istranslation'];
0 ignored issues
show
$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...
2086
		$catch_grammar = $data['catch_grammar'];
2087
2088
		if (!empty($client) && !empty($reftag) && !empty($tag) && !empty($filename))
2089
		{
2090
			try
2091
			{
2092
				$db                 = JFactory::getDbo();
2093
				$query	            = $db->getQuery(true);
2094
2095
				$search_client      = $db->quote($client);
2096
				$search_reftag      = $db->quote($reftag);
2097
				$search_tag         = $db->quote($tag);
2098
				$search_filename    = $db->quote($filename);
2099
				$search_key         = $db->quote($key);
2100
				$search_target_text = $db->quote($target_text);
2101
				$search_source_text = $db->quote($source_text);
2102
2103
				$query->select(
2104
						array	(
2105
							$db->quoteName('revised')
2106
							)
2107
						);
2108
				$query->from(
2109
						$db->quoteName('#__localise_revised_values')
2110
						);
2111
				$query->where(
2112
						$db->quoteName('client') . '= ' . $search_client
2113
						);
2114
				$query->where(
2115
						$db->quoteName('reftag') . '= ' . $search_reftag
2116
2117
						);
2118
				$query->where(
2119
						$db->quoteName('tag') . '= ' . $search_tag
2120
2121
						);
2122
				$query->where(
2123
						$db->quoteName('filename') . '= ' . $search_filename
2124
						);
2125
				$query->where(
2126
						$db->quoteName('key') . '= ' . $search_key
2127
						);
2128
				$query->where(
2129
						$db->quoteName('target_text') . '= ' . $search_target_text
2130
						);
2131
				$query->where(
2132
						$db->quoteName('source_text') . '= ' . $search_source_text
2133
						);
2134
2135
				$db->setQuery($query);
2136
2137
					if (!$db->query())
2138
					{
2139
						throw new Exception($db->getErrorMsg());
2140
					}
2141
			}
2142
2143
			catch (JException $e)
0 ignored issues
show
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...
2144
			{
2145
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_SEARCHING_REVISED_VALUES'), 'warning');
2146
2147
				return null;
2148
			}
2149
2150
			$result = $db->loadResult();
2151
2152
				if (!is_null($result))
2153
				{
2154
					return (int) $result;
2155
				}
2156
				elseif ($catch_grammar == '1')
2157
				{
2158
					return '0';
2159
				}
2160
				else
2161
				{
2162
					if (self::saveRevisedvalue($data))
2163
					{
2164
						return (int) $revised;
2165
					}
2166
					else
2167
					{
2168
						return null;
2169
					}
2170
				}
2171
		}
2172
2173
		return null;
2174
	}
2175
2176
	/**
2177
	 * Update revised changes
2178
	 *
2179
	 * @param   array  $data  The required data.
2180
	 *
2181
	 * @return  array
2182
	 *
2183
	 * @since   4.11
2184
	 */
2185
	public static function updateRevisedvalue($data)
2186
	{
2187
		$client      = $data['client'];
2188
		$reftag      = $data['reftag'];
2189
		$tag         = $data['tag'];
2190
		$filename    = $data['filename'];
2191
		$revised     = $data['revised'];
2192
		$key         = $data['key'];
2193
		$target_text = $data['target_text'];
2194
		$source_text = $data['source_text'];
2195
2196
		if (!empty($client) && !empty($reftag) && !empty($tag) && !empty($filename))
2197
		{
2198
			try
2199
			{
2200
				$db = JFactory::getDbo();
2201
2202
				$updated_client      = $db->quote($client);
2203
				$updated_reftag      = $db->quote($reftag);
2204
				$updated_tag         = $db->quote($tag);
2205
				$updated_filename    = $db->quote($filename);
2206
				$updated_revised     = $db->quote($revised);
2207
				$updated_key         = $db->quote($key);
2208
				$updated_target_text = $db->quote($target_text);
2209
				$updated_source_text = $db->quote($source_text);
2210
2211
				$query = $db->getQuery(true);
2212
2213
				$fields = array(
2214
					$db->quoteName('revised') . ' = ' . $updated_revised
2215
				);
2216
2217
				$conditions = array(
2218
					$db->quoteName('client') . ' = ' . $updated_client,
2219
					$db->quoteName('reftag') . ' = ' . $updated_reftag,
2220
					$db->quoteName('tag') . ' = ' . $updated_tag,
2221
					$db->quoteName('filename') . ' = ' . $updated_filename,
2222
					$db->quoteName('key') . ' = ' . $updated_key,
2223
					$db->quoteName('target_text') . ' = ' . $updated_target_text,
2224
					$db->quoteName('source_text') . ' = ' . $updated_source_text
2225
				);
2226
2227
				$query->update($db->quoteName('#__localise_revised_values'))->set($fields)->where($conditions);
2228
2229
				$db->setQuery($query);
2230
				$db->execute();
2231
			}
2232
2233
			catch (JException $e)
0 ignored issues
show
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...
2234
			{
2235
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_UPDATING_REVISED_VALUES'), 'warning');
2236
2237
				return false;
2238
			}
2239
2240
			return true;
2241
		}
2242
2243
		return false;
2244
	}
2245
2246
	/**
2247
	 * Save revised changes
2248
	 *
2249
	 * @param   array  $data  The required data.
2250
	 *
2251
	 * @return  array
2252
	 *
2253
	 * @since   4.11
2254
	 */
2255
	public static function saveRevisedvalue($data)
2256
	{
2257
		$client      = $data['client'];
2258
		$reftag      = $data['reftag'];
2259
		$tag         = $data['tag'];
2260
		$filename    = $data['filename'];
2261
		$revised     = $data['revised'];
2262
		$key         = $data['key'];
2263
		$target_text = $data['target_text'];
2264
		$source_text = $data['source_text'];
2265
2266
		if (!empty($client) && !empty($reftag) && !empty($tag) && !empty($filename))
2267
		{
2268
			try
2269
			{
2270
				$db = JFactory::getDbo();
2271
2272
				$saved_client      = $db->quote($client);
2273
				$saved_reftag      = $db->quote($reftag);
2274
				$saved_tag         = $db->quote($tag);
2275
				$saved_filename    = $db->quote($filename);
2276
				$saved_revised     = $db->quote($revised);
2277
				$saved_key         = $db->quote($key);
2278
				$saved_target_text = $db->quote($target_text);
2279
				$saved_source_text = $db->quote($source_text);
2280
2281
				$query = $db->getQuery(true);
2282
2283
				$columns = array('client', 'reftag', 'tag', 'filename', 'revised', 'key', 'target_text', 'source_text');
2284
2285
				$values = array($saved_client, $saved_reftag, $saved_tag, $saved_filename, $saved_revised, $saved_key, $saved_target_text, $saved_source_text);
2286
2287
				$query
2288
					->insert($db->quoteName('#__localise_revised_values'))
2289
					->columns($db->quoteName($columns))
2290
					->values(implode(',', $values));
2291
2292
				$db->setQuery($query);
2293
				$db->execute();
2294
			}
2295
2296
			catch (JException $e)
0 ignored issues
show
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...
2297
			{
2298
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_SAVING_REVISED_VALUES'), 'warning');
2299
2300
				return false;
2301
			}
2302
2303
			return true;
2304
		}
2305
2306
		return false;
2307
	}
2308
2309
	/**
2310
	 * Create the required folders for develop
2311
	 *
2312
	 * @param   array   $gh_data  Array with the data
2313
	 * @param   string  $index    If true, allow to create an index.html file
2314
	 *
2315
	 * @return  bolean
2316
	 *
2317
	 * @since   4.11
2318
	 */
2319
	public static function createFolder($gh_data = array(), $index = 'true')
2320
	{
2321
		$source_ref = $gh_data['customisedref'];
2322
2323
		if (!empty($gh_data) && isset($source_ref))
2324
		{
2325
		$full_path = JPATH_ROOT . '/media/com_localise/customisedref/github/'
2326
					. $gh_data['github_client']
2327
					. '/'
2328
					. $source_ref;
2329
2330
		$full_path = JFolder::makeSafe($full_path);
2331
2332
			if (!JFolder::create($full_path))
2333
			{
2334
			}
2335
2336
			if (JFolder::exists($full_path))
2337
			{
2338
				if ($index == 'true')
2339
				{
2340
				$cretate_index = self::createIndex($full_path);
2341
2342
					if ($cretate_index == 1)
2343
					{
2344
						return true;
2345
					}
2346
2347
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_CREATE_INDEX_FILE'), 'warning');
2348
2349
				return false;
2350
				}
2351
2352
			return true;
2353
			}
2354
			else
2355
			{
2356
				JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_ERROR_GITHUB_UNABLE_TO_CREATE_FOLDERS'), 'warning');
2357
2358
				return false;
2359
			}
2360
		}
2361
2362
	return false;
2363
	}
2364
2365
	/**
2366
	 * Creates an index.html file within folders for develop
2367
	 *
2368
	 * @param   string  $full_path  The full path.
2369
	 *
2370
	 * @return  bolean
2371
	 *
2372
	 * @since   4.11
2373
	 */
2374
	public static function createIndex($full_path = '')
2375
	{
2376
		if (!empty($full_path))
2377
		{
2378
		$path = JFolder::makeSafe($full_path . '/index.html');
2379
2380
		$index_content = '<!DOCTYPE html><title></title>';
2381
2382
			if (!JFile::exists($path))
2383
			{
2384
				JFile::write($path, $index_content);
2385
			}
2386
2387
			if (!JFile::exists($path))
2388
			{
2389
				return false;
2390
			}
2391
			else
2392
			{
2393
				return true;
2394
			}
2395
		}
2396
2397
	return false;
2398
	}
2399
2400
	/**
2401
	 * Gets the text changes.
2402
	 *
2403
	 * @param   array  $old  The string parts in reference.
2404
	 * @param   array  $new  The string parts in develop.
2405
	 *
2406
	 * @return  array
2407
	 *
2408
	 * @since   4.11
2409
	 */
2410
	public static function getTextchanges($old, $new)
2411
	{
2412
		$maxlen = 0;
2413
2414
		foreach ($old as $oindex => $ovalue)
2415
		{
2416
			$nkeys = array_keys($new, $ovalue);
2417
2418
			foreach ($nkeys as $nindex)
2419
			{
2420
				$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ? $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
0 ignored issues
show
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...
2421
2422
				if ($matrix[$oindex][$nindex] > $maxlen)
2423
				{
2424
					$maxlen = $matrix[$oindex][$nindex];
2425
					$omax = $oindex + 1 - $maxlen;
2426
					$nmax = $nindex + 1 - $maxlen;
2427
				}
2428
2429
			unset ($nkeys, $nindex);
2430
			}
2431
2432
		unset ($oindex, $ovalue);
2433
		}
2434
2435
		if ($maxlen == 0)
2436
		{
2437
			return array(array ('d' => $old, 'i' => $new));
2438
		}
2439
2440
		return array_merge(
2441
			self::getTextchanges(
2442
			array_slice($old, 0, $omax),
0 ignored issues
show
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...
2443
			array_slice($new, 0, $nmax)
0 ignored issues
show
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...
2444
			),
2445
			array_slice($new, $nmax, $maxlen),
2446
			self::getTextchanges(
2447
			array_slice($old, $omax + $maxlen),
2448
			array_slice($new, $nmax + $maxlen)
2449
			)
2450
			);
2451
	}
2452
2453
	/**
2454
	 * Gets the html text changes.
2455
	 *
2456
	 * @param   string  $old  The string in reference.
2457
	 * @param   string  $new  The string in develop.
2458
	 *
2459
	 * @return  string
2460
	 *
2461
	 * @since   4.11
2462
	 */
2463
	public static function htmlgetTextchanges($old, $new)
2464
	{
2465
		$text_changes = '';
2466
2467
		if ($old == $new)
2468
		{
2469
			return $text_changes;
2470
		}
2471
2472
		$old = str_replace('  ', 'LOCALISEDOUBLESPACES', $old);
2473
		$new = str_replace('  ', 'LOCALISEDOUBLESPACES', $new);
2474
2475
		$diff = self::getTextchanges(explode(' ', $old), explode(' ', $new));
2476
2477
		foreach ($diff as $k)
2478
		{
2479
			if (is_array($k))
2480
			{
2481
				$text_changes .= (!empty ($k['d'])?"LOCALISEDELSTART"
2482
					. implode(' ', $k['d']) . "LOCALISEDELSTOP ":'')
2483
					. (!empty($k['i']) ? "LOCALISEINSSTART"
2484
					. implode(' ', $k['i'])
2485
					. "LOCALISEINSSTOP " : '');
2486
			}
2487
			else
2488
			{
2489
				$text_changes .= $k . ' ';
2490
			}
2491
2492
		unset ($k);
2493
		}
2494
2495
		$text_changes = htmlspecialchars($text_changes);
2496
		$text_changes = preg_replace('/LOCALISEINSSTART/', "<ins class='diff_ins'>", $text_changes);
2497
		$text_changes = preg_replace('/LOCALISEINSSTOP/', "</ins>", $text_changes);
2498
		$text_changes = preg_replace('/LOCALISEDELSTART/', "<del class='diff_del'>", $text_changes);
2499
		$text_changes = preg_replace('/LOCALISEDELSTOP/', "</del>", $text_changes);
2500
		$double_spaces = '<span class="red-space"><font color="red">XX</font></span>';
2501
		$text_changes = str_replace('LOCALISEDOUBLESPACES', $double_spaces, $text_changes);
2502
2503
	return $text_changes;
2504
	}
2505
}
2506