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 ( 18eb75...946e63 )
by
unknown
05:39 queued 05:33
created

LocaliseModelTranslation::save()   D

Complexity

Conditions 13
Paths 120

Size

Total Lines 103
Code Lines 51

Duplication

Lines 12
Ratio 11.65 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 12
loc 103
rs 4.6605
cc 13
eloc 51
nc 120
nop 1

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @package     Com_Localise
4
 * @subpackage  model
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
jimport('joomla.filesystem.folder');
13
jimport('joomla.filesystem.file');
14
jimport('joomla.filesystem.stream');
15
jimport('joomla.client.helper');
16
jimport('joomla.access.rules');
17
18
/**
19
 * Translation Model class for the Localise component
20
 *
21
 * @since  1.0
22
 */
23
class LocaliseModelTranslation extends JModelAdmin
24
{
25
	protected $item;
26
27
	protected $contents;
28
29
	/**
30
	 * Method to auto-populate the model state.
31
	 *
32
	 * Note. Calling getState in this method will result in recursion.
33
	 *
34
	 * @param   string  $ordering   An optional ordering field.
35
	 * @param   string  $direction  An optional direction (asc|desc).
36
	 *
37
	 * @return  void
38
	 *
39
	 * @since   1.6
40
	 */
41
	protected function populateState($ordering = null, $direction = null)
42
	{
43
		$input = JFactory::getApplication()->input;
44
45
		// Get the infos
46
		$client   = $input->getCmd('client', '');
47
		$tag      = $input->getCmd('tag', '');
48
		$filename = $input->getCmd('filename', '');
49
		$storage  = $input->getCmd('storage', '');
50
51
		$this->setState('translation.client', !empty($client) ? $client : 'site');
52
		$this->setState('translation.tag', $tag);
53
		$this->setState('translation.filename', $filename);
54
		$this->setState('translation.storage', $storage);
55
56
		// Get the id
57
		$id = $input->getInt('id', '0');
58
		$this->setState('translation.id', $id);
59
60
		// Get the layout
61
		$layout = $input->getCmd('layout', 'edit');
62
		$this->setState('translation.layout', $layout);
63
64
		// Get the parameters
65
		$params = JComponentHelper::getParams('com_localise');
66
67
		// Get the reference tag
68
		$ref = $params->get('reference', 'en-GB');
69
		$this->setState('translation.reference', $ref);
70
71
		// Get the paths
72
		$path = LocaliseHelper::getTranslationPath($client, $tag, $filename, $storage);
73
74
		if ($filename == 'lib_joomla')
75
		{
76
			$refpath = LocaliseHelper::findTranslationPath('administrator', $ref, $filename);
77
78
			if (!JFile::exists($path))
79
			{
80
				$path2 = LocaliseHelper::getTranslationPath($client == 'administrator' ? 'site' : 'administrator', $tag, $filename, $storage);
81
82
				if (JFile::exists($path2))
83
				{
84
					$path = $path2;
85
				}
86
			}
87
		}
88
		else
89
		{
90
			$refpath = LocaliseHelper::findTranslationPath($client, $ref, $filename);
91
		}
92
93
		$this->setState('translation.path', $path);
94
		$this->setState('translation.refpath', $refpath);
95
	}
96
97
	/**
98
	 * Returns a Table object, always creating it.
99
	 *
100
	 * @param   type    $type    The table type to instantiate
101
	 * @param   string  $prefix  A prefix for the table class name. Optional.
102
	 * @param   array   $config  Configuration array for model. Optional.
103
	 *
104
	 * @return  JTable  A database object
105
	 */
106
	public function getTable($type = 'Localise', $prefix = 'LocaliseTable', $config = array())
107
	{
108
		return JTable::getInstance($type, $prefix, $config);
109
	}
110
111
	/**
112
	 * Get contents
113
	 *
114
	 * @return string
115
	 */
116
	public function getContents()
117
	{
118
		if (!isset($this->contents))
119
		{
120
			$path = $this->getState('translation.path');
121
122
			if (JFile::exists($path))
123
			{
124
				$this->contents = file_get_contents($path);
125
			}
126
			else
127
			{
128
				$this->contents = '';
129
			}
130
		}
131
132
		return $this->contents;
133
	}
134
135
	/**
136
	 * Get a translation
137
	 *
138
	 * @param   integer  $pk  The id of the primary key (Note unused by the function).
139
	 *
140
	 * @return  JObject|null  Object on success, null on failure.
141
	 */
142
	public function getItem($pk = null)
143
	{
144
		if (!isset($this->item))
145
		{
146
			$conf    = JFactory::getConfig();
147
			$caching = $conf->get('caching') >= 1;
148
149
			if ($caching)
150
			{
151
				$keycache   = $this->getState('translation.client') . '.' . $this->getState('translation.tag') . '.' .
152
					$this->getState('translation.filename') . '.' . 'translation';
153
				$cache      = JFactory::getCache('com_localise', '');
154
				$this->item = $cache->get($keycache);
155
156
				if ($this->item && $this->item->reference != $this->getState('translation.reference'))
157
				{
158
					$this->item = null;
159
				}
160
			}
161
			else
162
			{
163
				$this->item = null;
164
			}
165
166
			if (!$this->item)
167
			{
168
				$path = JFile::exists($this->getState('translation.path'))
169
					? $this->getState('translation.path')
170
					: $this->getState('translation.refpath');
171
172
				$params              = JComponentHelper::getParams('com_localise');
173
				$allow_develop       = $params->get('gh_allow_develop', 0);
174
				$gh_client           = $this->getState('translation.client');
175
				$tag                 = $this->getState('translation.tag');
176
				$reftag              = $this->getState('translation.reference');
177
				$refpath             = $this->getState('translation.refpath');
178
				$istranslation       = 0;
179
180
				if (!empty($tag) && $tag != $reftag)
181
				{
182
					$istranslation = 1;
183
				}
184
185
				$this->setState('translation.translatedkeys', array());
186
				$this->setState('translation.untranslatedkeys', array());
187
				$this->setState('translation.unchangedkeys', array());
188
				$this->setState('translation.textchangedkeys', array());
189
				$this->setState('translation.revisedchanges', array());
190
				$this->setState('translation.developdata', array());
191
192
				$translatedkeys   = $this->getState('translation.translatedkeys');
193
				$untranslatedkeys = $this->getState('translation.untranslatedkeys');
194
				$unchangedkeys    = $this->getState('translation.unchangedkeys');
195
				$textchangedkeys  = $this->getState('translation.textchangedkeys');
196
				$revisedchanges  = $this->getState('translation.revisedchanges');
197
				$developdata      = $this->getState('translation.developdata');
198
199
				$this->item = new JObject(
200
									array
201
										(
202
										'reference'           => $this->getState('translation.reference'),
203
										'bom'                 => 'UTF-8',
204
										'svn'                 => '',
205
										'version'             => '',
206
										'description'         => '',
207
										'creationdate'        => '',
208
										'author'              => '',
209
										'maincopyright'       => '',
210
										'additionalcopyright' => array(),
211
										'license'             => '',
212
										'exists'              => JFile::exists($this->getState('translation.path')),
213
										'istranslation'       => $istranslation,
214
										'developdata'         => (array) $developdata,
215
										'translatedkeys'      => (array) $translatedkeys,
216
										'untranslatedkeys'    => (array) $untranslatedkeys,
217
										'unchangedkeys'       => (array) $unchangedkeys,
218
										'textchangedkeys'     => (array) $textchangedkeys,
219
										'revisedchanges'      => (array) $revisedchanges,
220
										'unrevised'           => 0,
221
										'translatednews'      => 0,
222
										'unchangednews'       => 0,
223
										'translated'          => 0,
224
										'untranslated'        => 0,
225
										'unchanged'           => 0,
226
										'extra'               => 0,
227
										'total'               => 0,
228
										'linespath'           => 0,
229
										'linesrefpath'        => 0,
230
										'linesdevpath'        => 0,
231
										'linescustompath'     => 0,
232
										'complete'            => false,
233
										'source'              => '',
234
										'error'               => array()
235
										)
236
				);
237
238
				if (JFile::exists($path))
239
				{
240
					$devpath    = LocaliseHelper::searchDevpath($gh_client, $refpath);
241
					$custompath = LocaliseHelper::searchCustompath($gh_client, $refpath);
242
243
					if ($istranslation == 0 && $reftag == 'en-GB')
244
					{
245
						if (!empty($devpath))
246
						{
247
							if (!empty($custompath))
248
							{
249
								$this->item->source = LocaliseHelper::combineReferences($custompath, $devpath);
250
							}
251
							else
252
							{
253
								$this->item->source = LocaliseHelper::combineReferences($path, $devpath);
254
							}
255
						}
256
					}
257
					else
258
					{
259
						$this->item->source = file_get_contents($path);
260
					}
261
262
					$stream = new JStream;
263
					$stream->open($path);
264
					$begin  = $stream->read(4);
265
					$bom    = strtolower(bin2hex($begin));
266
267
					if ($bom == '0000feff')
268
					{
269
						$this->item->bom = 'UTF-32 BE';
270
					}
271
					else
272
					{
273
						if ($bom == 'feff0000')
274
						{
275
							$this->item->bom = 'UTF-32 LE';
276
						}
277
						else
278
						{
279
							if (substr($bom, 0, 4) == 'feff')
280
							{
281
								$this->item->bom = 'UTF-16 BE';
282
							}
283
							else
284
							{
285
								if (substr($bom, 0, 4) == 'fffe')
286
								{
287
									$this->item->bom = 'UTF-16 LE';
288
								}
289
							}
290
						}
291
					}
292
293
					$stream->seek(0);
294
					$continue   = true;
0 ignored issues
show
Unused Code introduced by
$continue 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...
295
					$lineNumber = 0;
296
297
					$isTranslationsView = JFactory::getApplication()->input->get('view') == 'translations';
298
299
					while (!$stream->eof())
300
					{
301
						$line = $stream->gets();
302
						$lineNumber++;
303
304
						if ($line[0] == '#')
305
						{
306
							$this->item->error[] = $lineNumber;
307
						}
308
						elseif ($line[0] == ';')
309
						{
310
							if (preg_match('/^(;).*(\$Id.*\$)/', $line, $matches))
311
							{
312
								$this->item->svn = $matches[2];
313
							}
314
							elseif (preg_match('/(;)\s*@?(\pL+):?.*/', $line, $matches))
315
							{
316
								switch (strtolower($matches[2]))
317
								{
318
									case 'note':
319
										preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
320
										$this->item->complete = $this->item->complete || strtolower($matches2[3]) == 'complete';
321
										break;
322
									case 'version':
323
										preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
324
										$this->item->version = $matches2[3];
325
										break;
326
									case 'desc':
327
									case 'description':
328
										preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
329
										$this->item->description = $matches2[3];
330
										break;
331
									case 'date':
332
										preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
333
										$this->item->creationdate = $matches2[3];
334
										break;
335 View Code Duplication
									case 'author':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
336
										if ($params->get('author') && !$isTranslationsView)
337
										{
338
											$this->item->author = $params->get('author');
339
										}
340
										else
341
										{
342
											preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
343
											$this->item->author = $matches2[3];
344
										}
345
										break;
346
									case 'copyright':
347
										preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
348
349
										if (empty($this->item->maincopyright))
350
										{
351
											if ($params->get('copyright') && !$isTranslationsView)
352
											{
353
												$this->item->maincopyright = $params->get('copyright');
354
											}
355
											else
356
											{
357
												$this->item->maincopyright = $matches2[3];
358
											}
359
										}
360
361
										if (empty($this->item->additionalcopyright))
362
										{
363
											if ($params->get('additionalcopyright') && !$isTranslationsView)
364
											{
365
												$this->item->additionalcopyright[] = $params->get('additionalcopyright');
366
											}
367
											else
368
											{
369
												$this->item->additionalcopyright[] = $matches2[3];
370
											}
371
										}
372
										break;
373 View Code Duplication
									case 'license':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
374
										if ($params->get('license') && !$isTranslationsView)
375
										{
376
											$this->item->license = $params->get('license');
377
										}
378
										else
379
										{
380
											preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
381
											$this->item->license = $matches2[3];
382
										}
383
										break;
384
									case 'package':
385
										preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
386
										$this->item->package = $matches2[3];
387
										break;
388
									case 'subpackage':
389
										preg_match('/(;)\s*@?(\pL+):?\s+(.*)/', $line, $matches2);
390
										$this->item->subpackage = $matches2[3];
391
										break;
392
									case 'link':
393
										break;
394 View Code Duplication
									default:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
395
										if (empty($this->item->author))
396
										{
397
											if ($params->get('author') && !$isTranslationsView)
398
											{
399
												$this->item->author = $params->get('author');
400
											}
401
											else
402
											{
403
												preg_match('/(;)\s*(.*)/', $line, $matches2);
404
												$this->item->author = $matches2[2];
405
											}
406
										}
407
										break;
408
								}
409
							}
410
						}
411
						else
412
						{
413
							break;
414
						}
415
					}
416
417
					if (empty($this->item->author) && $params->get('author') && !$isTranslationsView)
418
					{
419
						$this->item->author = $params->get('author');
420
					}
421
422
					if (empty($this->item->license) && $params->get('license') && !$isTranslationsView)
423
					{
424
						$this->item->license = $params->get('license');
425
					}
426
427
					if (empty($this->item->maincopyright) && $params->get('copyright') && !$isTranslationsView)
428
					{
429
						$this->item->maincopyright = $params->get('copyright');
430
					}
431
432
					if (empty($this->item->additionalcopyright) && $params->get('additionalcopyright') && !$isTranslationsView)
433
					{
434
						$this->item->additionalcopyright[] = $params->get('additionalcopyright');
435
					}
436
437
					while (!$stream->eof())
438
					{
439
						$line = $stream->gets();
440
						$lineNumber++;
441
442
						if (!preg_match('/^(|(\[[^\]]*\])|([A-Z][A-Z0-9_\*\-\.]*\s*=(\s*(("[^"]*")|(_QQ_)))+))\s*(;.*)?$/', $line))
443
						{
444
							$this->item->error[] = $lineNumber;
445
						}
446
					}
447
448
					if ($tag != $reftag)
449
					{
450
						if (JFile::exists($custompath))
451
						{
452
							$this->item->linescustompath = count(file($custompath));
453
						}
454
					}
455
456
					$stream->close();
457
				}
458
459
				$this->item->additionalcopyright = implode("\n", $this->item->additionalcopyright);
460
461
				if ($this->getState('translation.layout') != 'raw' && empty($this->item->error))
462
				{
463
					$sections = LocaliseHelper::parseSections($this->getState('translation.path'));
464
465
						if (!empty($custompath))
466
						{
467
							$refsections = LocaliseHelper::parseSections($custompath);
468
						}
469
						else
470
						{
471
							$refsections = LocaliseHelper::parseSections($this->getState('translation.refpath'));
472
						}
473
474
					$develop_client_path = JPATH_ROOT
475
								. '/media/com_localise/develop/github/joomla-cms/en-GB/'
476
								. $gh_client;
477
					$develop_client_path = JFolder::makeSafe($develop_client_path);
478
					$ref_file            = basename($this->getState('translation.refpath'));
479
					$develop_file_path   = "$develop_client_path/$ref_file";
480
					$new_keys            = array();
481
482
					if (JFile::exists($develop_file_path) && $allow_develop == 1 && $reftag == 'en-GB')
483
					{
484
						$info                  = array();
485
						$info['client']        = $gh_client;
486
						$info['reftag']        = 'en-GB';
487
						$info['tag']           = 'en-GB';
488
						$info['filename']      = $ref_file;
489
						$info['istranslation'] = $istranslation;
490
491
						$develop_sections = LocaliseHelper::parseSections($develop_file_path);
492
						$developdata      = LocaliseHelper::getDevelopchanges($info, $refsections, $develop_sections);
493
						$developdata['develop_file_path'] = '';
494
495
						if ($developdata['extra_keys']['amount'] > 0  || $developdata['text_changes']['amount'] > 0)
496
						{
497
							if ($developdata['extra_keys']['amount'] > 0)
498
							{
499
								$new_keys = $developdata['extra_keys']['keys'];
500
							}
501
502
							if ($developdata['text_changes']['amount'] > 0)
503
							{
504
								$textchangedkeys = $developdata['text_changes']['keys'];
505
								$this->item->textchangedkeys = $textchangedkeys;
506
								$this->setState('translation.textchangedkeys', $textchangedkeys);
507
508
								$changesdata['client'] = $gh_client;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$changesdata was never initialized. Although not strictly required by PHP, it is generally a good practice to add $changesdata = 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...
509
								$changesdata['reftag'] = $reftag;
510
511
									if ($istranslation == 0)
512
									{
513
										$changesdata['tag'] = $reftag;
514
									}
515
									else
516
									{
517
										$changesdata['tag'] = $tag;
518
									}
519
520
								$changesdata['filename'] = $ref_file;
521
522
								foreach ($textchangedkeys as $key_changed)
523
								{
524
									$target_text = $developdata['text_changes']['ref_in_dev'][$key_changed];
525
									$source_text = $developdata['text_changes']['ref'][$key_changed];
526
527
									$changesdata['revised']       = '0';
528
									$changesdata['key']           = $key_changed;
529
									$changesdata['target_text']   = $target_text;
530
									$changesdata['source_text']   = $source_text;
531
									$changesdata['istranslation'] = $istranslation;
532
									$changesdata['catch_grammar'] = '0';
533
534
									$change_status = LocaliseHelper::searchRevisedvalue($changesdata);
535
									$revisedchanges[$key_changed] = $change_status;
536
537
									if ($change_status == 1)
538
									{
539
										$developdata['text_changes']['revised']++;
540
									}
541
									else
542
									{
543
										$developdata['text_changes']['unrevised']++;
544
									}
545
								}
546
547
								$this->item->revisedchanges = $revisedchanges;
548
								$this->setState('translation.revisedchanges', $revisedchanges);
549
							}
550
551
							// When develop changes are present, replace the reference keys
552
							$refsections = $develop_sections;
553
554
							// And store the path for future calls
555
							$developdata['develop_file_path'] = $develop_file_path;
556
						}
557
					}
558
559
					if (!empty($refsections['keys']))
560
					{
561
						foreach ($refsections['keys'] as $key => $string)
562
						{
563
							$this->item->total++;
564
565
							if (!empty($sections['keys']) && array_key_exists($key, $sections['keys']) && $sections['keys'][$key] != '')
566
							{
567
								if ($sections['keys'][$key] != $string && $istranslation == 1)
568
								{
569
									if (array_key_exists($key, $revisedchanges) && $revisedchanges[$key] == 0)
570
									{
571
										$this->item->unrevised++;
572
										$translatedkeys[] = $key;
573
									}
574
									elseif (in_array($key, $new_keys))
575
									{
576
										$this->item->translatednews++;
577
										$translatedkeys[] = $key;
578
									}
579
									else
580
									{
581
										$this->item->translated++;
582
										$translatedkeys[] = $key;
583
									}
584
								}
585
								elseif ($istranslation == 0)
586
								{
587
									if (array_key_exists($key, $revisedchanges) && $revisedchanges[$key] == 0)
588
									{
589
										$this->item->unrevised++;
590
									}
591
									elseif (in_array($key, $new_keys))
592
									{
593
										$untranslatedkeys[] = $key;
594
									}
595
596
									$this->item->translated++;
597
								}
598
								else
599
								{
600
									if (in_array($key, $new_keys))
601
									{
602
										$this->item->unchangednews++;
603
									}
604
									else
605
									{
606
										$this->item->unchanged++;
607
									}
608
609
									$unchangedkeys[] = $key;
610
								}
611
							}
612
							elseif (!array_key_exists($key, $sections['keys']))
613
							{
614
								$this->item->untranslated++;
615
								$untranslatedkeys[] = $key;
616
							}
617
						}
618
					}
619
620
					$this->item->translatedkeys   = $translatedkeys;
621
					$this->item->untranslatedkeys = $untranslatedkeys;
622
					$this->item->unchangedkeys    = $unchangedkeys;
623
					$this->item->developdata      = $developdata;
624
625
					$this->setState('translation.translatedkeys', $translatedkeys);
626
					$this->setState('translation.untranslatedkeys', $untranslatedkeys);
627
					$this->setState('translation.unchangedkeys', $unchangedkeys);
628
					$this->setState('translation.developdata', $developdata);
629
630
					if (!empty($sections['keys']) && $istranslation == 1)
631
					{
632
						foreach ($sections['keys'] as $key => $string)
633
						{
634
							if (empty($refsections['keys']) || !array_key_exists($key, $refsections['keys']))
635
							{
636
								$this->item->extra++;
637
							}
638
						}
639
					}
640
641
					$done = $this->item->translated + $this->item->translatednews + $this->item->unchangednews;
642
643
					$this->item->completed = $this->item->total
644
						? intval(100 * $done / $this->item->total)
645
						: 100;
646
647
					$this->item->complete = $this->item->complete == 1 && $this->item->untranslated == 0 && $this->item->unrevised == 0
648
						? 1
649
						: ($this->item->completed == 100
650
							? 1
651
							: 0);
652
				}
653
654
				if ($this->getState('translation.id'))
655
				{
656
					$table = $this->getTable();
657
					$table->load($this->getState('translation.id'));
658
					$user = JFactory::getUser($table->checked_out);
659
					$this->item->setProperties($table->getProperties());
660
661
					if ($this->item->checked_out == JFactory::getUser()->id)
662
					{
663
						$this->item->checked_out = 0;
664
					}
665
666
					$this->item->editor = JText::sprintf('COM_LOCALISE_TEXT_TRANSLATION_EDITOR', $user->name, $user->username);
667
				}
668
669
				if ($caching)
670
				{
671
					$cache->store($this->item, $keycache);
0 ignored issues
show
Bug introduced by
The variable $cache 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...
Bug introduced by
The variable $keycache 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...
672
				}
673
674
				// Count the number of lines in the ini file to check max_input_vars
675
				if ($tag != $reftag)
676
				{
677
					if (JFile::exists($path))
678
					{
679
						$this->item->linespath = count(file($path));
680
					}
681
682
					if (JFile::exists($refpath))
683
					{
684
						$this->item->linesrefpath = count(file($refpath));
685
					}
686
687
					if (JFile::exists($develop_file_path))
688
					{
689
						$this->item->linesdevpath = count(file($develop_file_path));
0 ignored issues
show
Bug introduced by
The variable $develop_file_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...
690
					}
691
				}
692
				else
693
				{
694
					if (JFile::exists($path))
695
					{
696
						$this->item->linespath = count(file($path));
697
					}
698
				}
699
			}
700
		}
701
702
		return $this->item;
703
	}
704
705
	/**
706
	 * Method to get the record form.
707
	 *
708
	 * @param   array    $data      Data for the form.
709
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
710
	 *
711
	 * @return  mixed  A JForm object on success, false on failure
712
	 */
713
	public function getForm($data = array(), $loadData = true)
714
	{
715
		// Get the form.
716
		$form = $this->loadForm('com_localise.translation', 'translation', array('control'   => 'jform', 'load_data' => $loadData));
717
718
		$params = JComponentHelper::getParams('com_localise');
719
720
		// Set fields readonly if localise global params exist
721
		if ($params->get('author'))
722
		{
723
			$form->setFieldAttribute('author', 'readonly', 'true');
724
		}
725
726
		if ($params->get('copyright'))
727
		{
728
			$form->setFieldAttribute('maincopyright', 'readonly', 'true');
729
		}
730
731
		if ($params->get('additionalcopyright'))
732
		{
733
			$form->setFieldAttribute('additionalcopyright', 'readonly', 'true');
734
		}
735
736
		if ($params->get('license'))
737
		{
738
			$form->setFieldAttribute('license', 'readonly', 'true');
739
		}
740
741
		return $form;
742
	}
743
744
	/**
745
	 * Method to get the data that should be injected in the form.
746
	 *
747
	 * @return  array  The default data is an empty array.
748
	 */
749
	protected function loadFormData()
750
	{
751
		return $this->getItem();
752
	}
753
754
	/**
755
	 * Method to get the ftp form.
756
	 *
757
	 * @return  mixed  A JForm object on success, false on failure or not ftp
758
	 */
759 View Code Duplication
	public function getFormFtp()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
760
	{
761
		// Get the form.
762
		$form = $this->loadForm('com_localise.ftp', 'ftp');
763
764
		if (empty($form))
765
		{
766
			return false;
767
		}
768
769
		// Check for an error.
770
		if (JError::isError($form))
771
		{
772
			$this->setError($form->getMessage());
773
774
			return false;
775
		}
776
777
		return $form;
778
	}
779
780
	/**
781
	 * Method to allow derived classes to preprocess the form.
782
	 *
783
	 * @param   JForm   $form   A form object.
784
	 * @param   mixed   $item   The data expected for the form.
785
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
786
	 *
787
	 * @throws  Exception if there is an error in the form event.
788
	 * @return  JForm
789
	 */
790
	protected function preprocessForm(JForm $form, $item, $group = 'content')
791
	{
792
		// Initialize variables.
793
		$filename = $this->getState('translation.filename');
794
		$client   = $this->getState('translation.client');
795
		$tag      = $this->getState('translation.tag');
796
		$origin   = LocaliseHelper::getOrigin($filename, $client);
797
		$app      = JFactory::getApplication();
798
		$false    = false;
0 ignored issues
show
Unused Code introduced by
$false 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...
799
800
		$have_develop        = 0;
801
		$developdata         = array();
802
		$revisedchanges      = array();
803
		$istranslation       = '';
804
		$extras_amount       = 0;
0 ignored issues
show
Unused Code introduced by
$extras_amount 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...
805
		$text_changes_amount = 0;
0 ignored issues
show
Unused Code introduced by
$text_changes_amount 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...
806
807
		// Compute all known languages
808
		static $languages = array();
809
		jimport('joomla.language.language');
810
811
		if (!array_key_exists($client, $languages))
812
		{
813
			$languages[$client] = JLanguage::getKnownLanguages(constant('LOCALISEPATH_' . strtoupper($client)));
814
		}
815
816
		if (is_object($item))
817
		{
818
			$form->setFieldAttribute('legend', 'unchanged', $item->unchanged, 'legend');
819
			$form->setFieldAttribute('legend', 'translated', $item->translated, 'legend');
820
			$form->setFieldAttribute('legend', 'untranslated', $item->total - $item->translated - $item->unchanged, 'legend');
821
			$form->setFieldAttribute('legend', 'extra', $item->extra, 'legend');
822
823
			$developdata    = $item->developdata;
824
			$revisedchanges = $item->revisedchanges;
825
			$istranslation  = $item->istranslation;
826
		}
827
828
		if ($this->getState('translation.layout') != 'raw')
829
		{
830
			$this->setState('translation.devpath', '');
831
832
			if (!empty($developdata))
833
			{
834
				$extras_amount       = $developdata['extra_keys']['amount'];
835
				$text_changes_amount = $developdata['text_changes']['amount'];
836
				$refpath             = $this->getState('translation.refpath');
837
838
				$custompath          = LocaliseHelper::searchCustompath($client, $refpath);
839
840
				if ($istranslation == '0')
841
				{
842
					if (!empty($custompath))
843
					{
844
						$refpath     = $custompath;
845
						$path        = $refpath;
0 ignored issues
show
Unused Code introduced by
$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...
846
						$refsections = LocaliseHelper::parseSections($refpath);
847
						$sections    = $refsections;
848
					}
849
					else
850
					{
851
						$refpath     = $this->getState('translation.refpath');
852
						$path        = $refpath;
0 ignored issues
show
Unused Code introduced by
$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...
853
						$refsections = LocaliseHelper::parseSections($refpath);
854
						$sections    = $refsections;
855
					}
856
				}
857
				else
858
				{
859
					if (!empty($custompath))
860
					{
861
						$refpath     = $custompath;
862
						$path        = $this->getState('translation.path');
863
						$refsections = LocaliseHelper::parseSections($refpath);
864
						$sections    = LocaliseHelper::parseSections($path);
865
					}
866 View Code Duplication
					else
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
867
					{
868
						$refpath     = $this->getState('translation.refpath');
869
						$path        = $this->getState('translation.path');
870
						$refsections = LocaliseHelper::parseSections($refpath);
871
						$sections    = LocaliseHelper::parseSections($path);
872
					}
873
				}
874
875
				if ($extras_amount > 0  || $text_changes_amount > 0)
876
				{
877
					$have_develop      = 1;
878
					$develop_file_path = $developdata['develop_file_path'];
879
					$develop_sections  = LocaliseHelper::parseSections($develop_file_path);
880
					$oldref            = $refsections;
881
					$refsections       = $develop_sections;
882
					$refpath           = $develop_file_path;
883
884
					$this->setState('translation.devpath', $develop_file_path);
885
				}
886
			}
887 View Code Duplication
			else
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
888
			{
889
				$path        = $this->getState('translation.path');
890
				$refpath     = $this->getState('translation.refpath');
891
				$sections    = LocaliseHelper::parseSections($path);
892
				$refsections = LocaliseHelper::parseSections($refpath);
893
			}
894
895
			$addform     = new SimpleXMLElement('<form />');
896
897
			$group = $addform->addChild('fields');
898
			$group->addAttribute('name', 'strings');
899
900
			$fieldset = $group->addChild('fieldset');
901
			$fieldset->addAttribute('name', 'JDEFAULT');
902
			$fieldset->addAttribute('label', 'JDEFAULT');
903
904
			if (JFile::exists($refpath))
905
			{
906
				$stream = new JStream;
907
				$stream->open($refpath);
908
				$header     = true;
909
				$lineNumber = 0;
910
911
				while (!$stream->eof())
912
				{
913
					$line = $stream->gets();
914
					$lineNumber++;
915
916
					// Blank lines
917
					if (preg_match('/^\s*$/', $line))
918
					{
919
						$header = true;
920
						$field  = $fieldset->addChild('field');
921
						$field->addAttribute('label', '');
922
						$field->addAttribute('type', 'spacer');
923
						$field->addAttribute('class', 'text');
924
						continue;
925
					}
926
					// Section lines
927
					elseif (preg_match('/^\[([^\]]*)\]\s*$/', $line, $matches))
928
					{
929
						$header = false;
930
						$form->load($addform, false);
931
						$section = $matches[1];
932
						$addform = new SimpleXMLElement('<form />');
933
						$group   = $addform->addChild('fields');
934
						$group->addAttribute('name', 'strings');
935
						$fieldset = $group->addChild('fieldset');
936
						$fieldset->addAttribute('name', $section);
937
						$fieldset->addAttribute('label', $section);
938
						continue;
939
					}
940
					// Comment lines
941
					elseif (!$header && preg_match('/^;(.*)$/', $line, $matches))
942
					{
943
						$key   = $matches[1];
944
						$field = $fieldset->addChild('field');
945
						$field->addAttribute('label', $key);
946
						$field->addAttribute('type', 'spacer');
947
						$field->addAttribute('class', 'text');
948
						continue;
949
					}
950
					// Key lines
951
					elseif (preg_match('/^([A-Z][A-Z0-9_\*\-\.]*)\s*=/', $line, $matches))
952
					{
953
						$header     = false;
954
						$key        = $matches[1];
955
						$field      = $fieldset->addChild('field');
956
957
						if ($have_develop == '1' && $istranslation == '0' && array_key_exists($key, $oldref['keys']))
958
						{
959
							$string = $oldref['keys'][$key];
0 ignored issues
show
Bug introduced by
The variable $oldref 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...
960
							$translated = isset($sections['keys'][$key]);
961
							$modified   = $translated && $sections['keys'][$key] != $oldref['keys'][$key];
962
						}
963
						else
964
						{
965
							$string = $refsections['keys'][$key];
966
							$translated = isset($sections['keys'][$key]);
967
							$modified   = $translated && $sections['keys'][$key] != $refsections['keys'][$key];
968
						}
969
970
						$status     = $modified
971
							? 'translated'
972
							: ($translated
973
								? 'unchanged'
974
								: 'untranslated');
975
						$default    = $translated
976
							? $sections['keys'][$key]
977
							: '';
978
979
						$field->addAttribute('istranslation', $istranslation);
980
						$field->addAttribute('istextchange', 0);
981
						$field->addAttribute('isextraindev', 0);
982
983
						if ($have_develop == '1' && in_array($key, $developdata['text_changes']['keys']))
984
						{
985
							$change     = $developdata['text_changes']['diff'][$key];
986
							$sourcetext = $developdata['text_changes']['ref'][$key];
987
							$targettext = $developdata['text_changes']['ref_in_dev'][$key];
988
989
							$label   = '<b>'
990
								. $key
991
								. '</b><br /><p class="text_changes">'
992
								. $change
993
								. '</p>';
994
995
							$field->attributes()->istextchange = 1;
996
							$field->addAttribute('changestatus', $revisedchanges[$key]);
997
							$field->addAttribute('sourcetext', $sourcetext);
998
							$field->addAttribute('targettext', $targettext);
999
						}
1000
						elseif ($have_develop == '1' && in_array($key, $developdata['extra_keys']['keys']))
1001
						{
1002
							$label   = '<span class="new_word"><b>['
1003
								. JText::_('COM_LOCALISE_NEW_KEY_IN_DEVELOP')
1004
								. ']</b> </span><b>'
1005
								. $key
1006
								. '</b><br />'
1007
								. htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
1008
1009
							$field->attributes()->isextraindev = 1;
1010
						}
1011
						else
1012
						{
1013
							$label   = '<b>'
1014
								. $key
1015
								. '</b><br />'
1016
								. htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
1017
						}
1018
1019
						$field->addAttribute('status', $status);
1020
						$field->addAttribute('description', $string);
1021
1022
						if ($default)
1023
						{
1024
							$field->addAttribute('default', $default);
1025
						}
1026
						else
1027
						{
1028
							$field->addAttribute('default', $string);
1029
						}
1030
1031
						$field->addAttribute('label', $label);
1032
						$field->addAttribute('name', $key);
1033
						$field->addAttribute('type', 'key');
1034
						$field->addAttribute('filter', 'raw');
1035
						continue;
1036
					}
1037
					elseif (!preg_match('/^(|(\[[^\]]*\])|([A-Z][A-Z0-9_\*\-\.]*\s*=(\s*(("[^"]*")|(_QQ_)))+))\s*(;.*)?$/', $line))
1038
					{
1039
						$this->item->error[] = $lineNumber;
1040
					}
1041
				}
1042
1043
				$stream->close();
1044
				$newstrings = false;
1045
1046
				if (!empty($sections['keys']))
1047
				{
1048
					foreach ($sections['keys'] as $key => $string)
1049
					{
1050
						if (!isset($refsections['keys'][$key]))
1051
						{
1052
							if (!$newstrings)
1053
							{
1054
								$newstrings = true;
1055
								$form->load($addform, false);
1056
								$section = 'COM_LOCALISE_TEXT_TRANSLATION_NOTINREFERENCE';
1057
								$addform = new SimpleXMLElement('<form />');
1058
								$group   = $addform->addChild('fields');
1059
								$group->addAttribute('name', 'strings');
1060
								$fieldset = $group->addChild('fieldset');
1061
								$fieldset->addAttribute('name', $section);
1062
								$fieldset->addAttribute('label', $section);
1063
							}
1064
1065
							$field   = $fieldset->addChild('field');
1066
							$status  = 'extra';
1067
							$default = $string;
1068
							$label   = '<b>' . $key . '</b>';
1069
							$field->addAttribute('status', $status);
1070
							$field->addAttribute('description', $string);
1071
1072
							if ($default)
1073
							{
1074
								$field->addAttribute('default', $default);
1075
							}
1076
							else
1077
							{
1078
								$field->addAttribute('default', $string);
1079
							}
1080
1081
							$field->addAttribute('label', $label);
1082
							$field->addAttribute('name', $key);
1083
							$field->addAttribute('type', 'key');
1084
							$field->addAttribute('filter', 'raw');
1085
						}
1086
					}
1087
				}
1088
			}
1089
1090
			$form->load($addform, false);
1091
		}
1092
1093
		// Check the session for previously entered form data.
1094
		$data = $app->getUserState('com_localise.edit.translation.data', array());
1095
1096
		// Bind the form data if present.
1097
		if (!empty($data))
1098
		{
1099
			$form->bind($data);
1100
		}
1101
1102
		if ($origin != '_thirdparty' && $origin != '_override')
1103
		{
1104
			$packages = LocaliseHelper::getPackages();
1105
			$package  = $packages[$origin];
1106
1107
			if (!empty($package->author))
1108
			{
1109
				$form->setValue('author', $package->author);
1110
				$form->setFieldAttribute('author', 'readonly', 'true');
1111
			}
1112
1113
			if (!empty($package->copyright))
1114
			{
1115
				$form->setValue('maincopyright', $package->copyright);
1116
				$form->setFieldAttribute('maincopyright', 'readonly', 'true');
1117
			}
1118
1119
			if (!empty($package->license))
1120
			{
1121
				$form->setValue('license', $package->license);
1122
				$form->setFieldAttribute('license', 'readonly', 'true');
1123
			}
1124
		}
1125
1126
		if ($form->getValue('description') == '' && array_key_exists($tag, $languages[$client]))
1127
		{
1128
			$form->setValue('description', $filename . ' ' . $languages[$client][$tag]['name']);
1129
		}
1130
1131
		return $form;
1132
	}
1133
1134
	/**
1135
	 * Save a file
1136
	 *
1137
	 * @param   array  $data  Array that represents a file
1138
	 *
1139
	 * @return bool
1140
	 */
1141
	public function saveFile($data)
1142
	{
1143
		$client     = $this->getState('translation.client');
1144
		$tag        = $this->getState('translation.tag');
1145
		$reftag     = $this->getState('translation.reference');
1146
		$path       = $this->getState('translation.path');
1147
		$refpath    = $this->getState('translation.refpath');
1148
		$devpath    = LocaliseHelper::searchDevpath($client, $refpath);
1149
		$custompath = LocaliseHelper::searchCustompath($client, $refpath);
1150
		$exists     = JFile::exists($path);
1151
		$refexists  = JFile::exists($refpath);
1152
1153
		if ($refexists && !empty($devpath))
1154
		{
1155
			if ($reftag == 'en-GB' && $tag == 'en-GB' && !empty($custompath))
1156
			{
1157
				$params             = JComponentHelper::getParams('com_localise');
1158
				$customisedref      = $params->get('customisedref', '0');
1159
				$custom_short_path  = '../media/com_localise/customisedref/github/'
0 ignored issues
show
Unused Code introduced by
$custom_short_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...
1160
							. $client
1161
							. '/'
1162
							. $customisedref;
1163
1164
				// The saved file is not using the core language folders.
1165
				$path   = $custompath;
1166
				$exists = JFile::exists($path);
1167
1168
				$ref_file         = basename($refpath);
1169
				$custom_file_path = JFolder::makeSafe("$custompath/$ref_file");
0 ignored issues
show
Unused Code introduced by
$custom_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...
1170
			}
1171
			elseif ($reftag == 'en-GB' &&  $tag != 'en-GB')
1172
			{
1173
				// It is a translation with the file in develop as reference.
1174
				$refpath = $devpath;
1175
			}
1176
		}
1177
1178
		// Set FTP credentials, if given.
1179
		JClientHelper::setCredentialsFromRequest('ftp');
1180
		$ftp = JClientHelper::getCredentials('ftp');
1181
1182
		// Try to make the file writeable.
1183 View Code Duplication
		if ($exists && !$ftp['enabled'] && JPath::isOwner($path) && !JPath::setPermissions($path, '0644'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1184
		{
1185
			$this->setError(JText::sprintf('COM_LOCALISE_ERROR_TRANSLATION_WRITABLE', $path));
1186
1187
			return false;
1188
		}
1189
1190
		if (array_key_exists('source', $data))
1191
		{
1192
			$contents = $data['source'];
1193
		}
1194
		else
1195
		{
1196
			$data['description']  = str_replace(array("\r\n", "\n", "\r"), " ", $data['description']);
1197
			$additionalcopyrights = trim($data['additionalcopyright']);
1198
1199
			if (empty($additionalcopyrights))
1200
			{
1201
				$additionalcopyrights = array();
1202
			}
1203
			else
1204
			{
1205
				$additionalcopyrights = explode("\n", $additionalcopyrights);
1206
			}
1207
1208
			$contents2 = '';
1209
1210
			if (!empty($data['svn']))
1211
			{
1212
				$contents2 .= "; " . $data['svn'] . "\n;\n";
1213
			}
1214
1215
			if (!empty($data['package']))
1216
			{
1217
				$contents2 .= "; @package     " . $data['package'] . "\n";
1218
			}
1219
1220
			if (!empty($data['subpackage']))
1221
			{
1222
				$contents2 .= "; @subpackage  " . $data['subpackage'] . "\n";
1223
			}
1224
1225
			if (!empty($data['description']) && $data['description'] != '[Description] [Name of language]([Country code])')
1226
			{
1227
				$contents2 .= "; @description " . $data['description'] . "\n";
1228
			}
1229
1230
			if (!empty($data['version']))
1231
			{
1232
				$contents2 .= "; @version     " . $data['version'] . "\n";
1233
			}
1234
1235
			if (!empty($data['creationdate']))
1236
			{
1237
				$contents2 .= "; @date        " . $data['creationdate'] . "\n";
1238
			}
1239
1240
			if (!empty($data['author']))
1241
			{
1242
				$contents2 .= "; @author      " . $data['author'] . "\n";
1243
			}
1244
1245
			if (!empty($data['maincopyright']))
1246
			{
1247
				$contents2 .= "; @copyright   " . $data['maincopyright'] . "\n";
1248
			}
1249
1250
			foreach ($additionalcopyrights as $copyright)
1251
			{
1252
				$contents2 .= "; @copyright   " . $copyright . "\n";
1253
			}
1254
1255
			if (!empty($data['license']))
1256
			{
1257
				$contents2 .= "; @license     " . $data['license'] . "\n";
1258
			}
1259
1260
			if (array_key_exists('complete', $data) && ($data['complete'] == '1'))
1261
			{
1262
				$this->setState('translation.complete', 1);
1263
				$contents2 .= "; @note        Complete\n";
1264
			}
1265
			else
1266
			{
1267
				$this->setState('translation.complete', 0);
1268
			}
1269
1270
			$contents2 .= "; @note        Client " . ucfirst($client) . "\n";
1271
			$contents2 .= "; @note        All ini files need to be saved as UTF-8\n\n";
1272
1273
			$contents = array();
1274
			$stream   = new JStream;
1275
1276
			if ($exists)
1277
			{
1278
				$stream->open($path);
1279
1280 View Code Duplication
				while (!$stream->eof())
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1281
				{
1282
					$line = $stream->gets();
1283
1284
					// Comment lines
1285
					if (preg_match('/^(;.*)$/', $line, $matches))
1286
					{
1287
						// $contents[] = $matches[1]."\n";
1288
					}
1289
					else
1290
					{
1291
						break;
1292
					}
1293
				}
1294
1295
				if ($refexists)
1296
				{
1297
					$stream->close();
1298
					$stream->open($refpath);
1299
1300 View Code Duplication
					while (!$stream->eof())
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1301
					{
1302
						$line = $stream->gets();
1303
1304
						// Comment lines
1305
						if (!preg_match('/^(;.*)$/', $line, $matches))
1306
						{
1307
							break;
1308
						}
1309
					}
1310
				}
1311
			}
1312
			else
1313
			{
1314
				$stream->open($refpath);
1315
1316
				while (!$stream->eof())
1317
				{
1318
					$line = $stream->gets();
1319
1320
					// Comment lines
1321
					if (preg_match('/^(;.*)$/', $line, $matches))
1322
					{
1323
						$contents[] = $matches[1] . "\n";
1324
					}
1325
					else
1326
					{
1327
						break;
1328
					}
1329
				}
1330
			}
1331
1332
			$strings = $data['strings'];
1333
1334
			while (!$stream->eof())
1335
			{
1336
			// Mounting the language file in this way will help to avoid save files with errors at the content.
1337
1338
				// Blank lines
1339
				if (preg_match('/^\s*$/', $line))
1340
				{
1341
					$contents[] = "\n";
1342
				}
1343
				// Comments lines
1344
				elseif (preg_match('/^(;.*)$/', $line, $matches))
0 ignored issues
show
Bug introduced by
The variable $line 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...
1345
				{
1346
					$contents[] = $matches[1] . "\n";
1347
				}
1348
				// Section lines
1349
				elseif (preg_match('/^\[([^\]]*)\]\s*$/', $line, $matches))
1350
				{
1351
					$contents[] = $matches[1] . "\n";
1352
				}
1353
				// Key lines
1354
				elseif (preg_match('/^([A-Z][A-Z0-9_\*\-\.]*)\s*=/', $line, $matches))
1355
				{
1356
					$key = $matches[1];
1357
1358
					if (isset($strings[$key]))
1359
					{
1360
						$contents[] = $key . '="' . str_replace('"', '"_QQ_"', $strings[$key]) . "\"\n";
1361
						unset($strings[$key]);
1362
					}
1363
				}
1364
				// Content with EOL
1365
				elseif (preg_split("/\\r\\n|\\r|\\n/", $line))
1366
				{
1367
					// $this->setError(JText::sprintf('COM_LOCALISE_WRONG_LINE_CONTENT', htmlspecialchars($line)));
1368
					$application = JFactory::getApplication();
1369
					$application->enqueueMessage(JText::sprintf('COM_LOCALISE_WRONG_LINE_CONTENT', htmlspecialchars($line)), 'warning');
1370
				}
1371
				// Wrong lines
1372
				else
1373
				{
1374
					// $this->setError(JText::sprintf('COM_LOCALISE_WRONG_LINE_CONTENT', htmlspecialchars($line)));
1375
					$application = JFactory::getApplication();
1376
					$application->enqueueMessage(JText::sprintf('COM_LOCALISE_WRONG_LINE_CONTENT', htmlspecialchars($line)), 'warning');
1377
				}
1378
1379
				$line = $stream->gets();
1380
			}
1381
1382
			if (!empty($strings))
1383
			{
1384
				$contents[] = "\n[New Strings]\n\n";
1385
1386
				foreach ($strings as $key => $string)
1387
				{
1388
					$contents[] = $key . '="' . str_replace('"', '"_QQ_"', $string) . "\"\n";
1389
				}
1390
			}
1391
1392
			$stream->close();
1393
			$contents = implode($contents);
1394
			$contents = $contents2 . $contents;
1395
		}
1396
1397
		$return = JFile::write($path, $contents);
1398
1399
		// Try to make the template file unwriteable.
1400
1401
		// Get the parameters
1402
		$coparams = JComponentHelper::getParams('com_localise');
1403
1404
		// Get the file save permission
1405
		$fsper = $coparams->get('filesavepermission', '0444');
1406
1407
		if (!$ftp['enabled'] && JPath::isOwner($path) && !JPath::setPermissions($path, $fsper))
1408
		{
1409
			$this->setError(JText::sprintf('COM_LOCALISE_ERROR_TRANSLATION_UNWRITABLE', $path));
1410
1411
			return false;
1412
		}
1413
		else
1414
		{
1415
			if (!$return)
1416
			{
1417
				$this->setError(JText::sprintf('COM_LOCALISE_ERROR_TRANSLATION_FILESAVE', $path));
1418
1419
				return false;
1420
			}
1421
			elseif ($reftag == 'en-GB' && $tag == 'en-GB' && !empty($custompath))
1422
			{
1423
				$params             = JComponentHelper::getParams('com_localise');
1424
				$customisedref      = $params->get('customisedref', '0');
1425
				$custom_short_path  = '../media/com_localise/customisedref/github/'
1426
							. $client
1427
							. '/'
1428
							. $customisedref;
1429
1430
				JFactory::getApplication()->enqueueMessage(
1431
					JText::_('COM_LOCALISE_NOTICE_CUSTOM_EN_GB_FILE_SAVED') . $custom_short_path,
1432
					'notice');
1433
			}
1434
		}
1435
1436
		// Remove the cache
1437
		$conf    = JFactory::getConfig();
1438
		$caching = $conf->get('caching') >= 1;
1439
1440
		if ($caching)
1441
		{
1442
			$keycache = $this->getState('translation.client') . '.'
1443
				. $this->getState('translation.tag') . '.'
1444
				. $this->getState('translation.filename') . '.' . 'translation';
1445
			$cache    = JFactory::getCache('com_localise', '');
1446
			$cache->remove($keycache);
1447
		}
1448
	}
1449
1450
	/**
1451
	 * Saves a translation
1452
	 *
1453
	 * @param   array  $data  translation to be saved
1454
	 *
1455
	 * @return bool
1456
	 */
1457
	public function save($data)
1458
	{
1459
		// Fix DOT saving issue
1460
		$input = JFactory::getApplication()->input;
1461
1462
		$formData = $input->get('jform', array(), 'ARRAY');
1463
1464
		if (!empty($formData['strings']))
1465
		{
1466
			$data['strings'] = $formData['strings'];
1467
1468
			if (!empty($formData['text_changes']))
1469
			{
1470
				$data['text_changes'] = $formData['text_changes'];
1471
				$data['source_text_changes'] = $formData['source_text_changes'];
1472
				$data['target_text_changes'] = $formData['target_text_changes'];
1473
1474
				$changes_data = array();
1475
				$changes_data['client'] = $this->getState('translation.client');
1476
				$changes_data['reftag'] = $this->getState('translation.reference');
1477
				$changes_data['tag'] = $this->getState('translation.tag');
1478
				$changes_data['filename'] = basename($this->getState('translation.refpath'));
1479
$died = '';
0 ignored issues
show
Unused Code introduced by
$died 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...
1480
1481
				foreach ($data['text_changes'] as $key => $revised)
1482
				{
1483
					$changes_data['revised'] = "0";
1484
1485
					if ($revised == '1' || $revised == 'true')
1486
					{
1487
						$changes_data['revised'] = "1";
1488
					}
1489
1490
					$changes_data['key'] = $key;
1491
					$changes_data['target_text'] = $data['target_text_changes'][$key];
1492
					$changes_data['source_text'] = $data['source_text_changes'][$key];
1493
1494
					LocaliseHelper::updateRevisedvalue($changes_data);
1495
				}
1496
			}
1497
		}
1498
1499
		// Special case for lib_joomla
1500
		if ($this->getState('translation.filename') == 'lib_joomla')
1501
		{
1502
			$tag = $this->getState('translation.tag');
1503
1504 View Code Duplication
			if (JFolder::exists(JPATH_SITE . "/language/$tag"))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1505
			{
1506
				$this->setState('translation.client', 'site');
1507
				$this->setState('translation.path', JPATH_SITE . "/language/$tag/$tag.lib_joomla.ini");
1508
				$this->saveFile($data);
1509
			}
1510
1511 View Code Duplication
			if (JFolder::exists(JPATH_ADMINISTRATOR . "/language/$tag"))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1512
			{
1513
				$this->setState('translation.client', 'administrator');
1514
				$this->setState('translation.path', JPATH_ADMINISTRATOR . "/language/$tag/$tag.lib_joomla.ini");
1515
				$this->saveFile($data);
1516
			}
1517
		}
1518
		else
1519
		{
1520
			$this->saveFile($data);
1521
		}
1522
1523
		// Bind the rules.
1524
		$table = $this->getTable();
1525
		$table->load($data['id']);
1526
1527
		if (isset($data['rules']))
1528
		{
1529
			$rules = new JAccessRules($data['rules']);
1530
			$table->setRules($rules);
1531
		}
1532
1533
		// Check the data.
1534
		if (!$table->check())
1535
		{
1536
			$this->setError($table->getError());
1537
1538
			return false;
1539
		}
1540
1541
		// Store the data.
1542
		if (!$table->store())
1543
		{
1544
			$this->setError($table->getError());
1545
1546
			return false;
1547
		}
1548
1549
		if ($this->getState('translation.complete') == 1)
1550
		{
1551
			JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_NOTICE_TRANSLATION_COMPLETE'), 'notice');
1552
		}
1553
		else
1554
		{
1555
			JFactory::getApplication()->enqueueMessage(JText::_('COM_LOCALISE_NOTICE_TRANSLATION_NOT_COMPLETE'), 'notice');
1556
		}
1557
1558
		return true;
1559
	}
1560
}
1561