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.

LocaliseModelPackageFile   F
last analyzed

Complexity

Total Complexity 76

Size/Duplication

Total Lines 817
Duplicated Lines 49.08 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 401
loc 817
rs 2.1029
c 0
b 0
f 0
wmc 76
lcom 1
cbo 1

8 Methods

Rating   Name   Duplication   Size   Complexity  
A populateState() 0 12 1
A getTable() 0 4 1
A getForm() 24 24 3
A loadFormData() 16 16 2
A getFormFtp() 20 20 3
C getItem() 36 126 13
F save() 110 286 29
F download() 195 259 24

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like LocaliseModelPackageFile often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use LocaliseModelPackageFile, and based on these observations, apply Extract Interface, too.

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.client.helper');
15
16
/**
17
 * Package Model class for the Localise component
18
 *
19
 * @package     Extensions.Components
20
 * @subpackage  Localise
21
 *
22
 * @since       1.0
23
 */
24
class LocaliseModelPackageFile extends JModelAdmin
25
{
26
	/**
27
	 * Method to auto-populate the model state.
28
	 *
29
	 * Note. Calling getState in this method will result in recursion.
30
	 *
31
	 * @param   string  $ordering   An optional ordering field.
32
	 * @param   string  $direction  An optional direction (asc|desc).
33
	 *
34
	 * @return  void
35
	 *
36
	 * @since   1.6
37
	 */
38
	protected function populateState($ordering = null, $direction = null)
39
	{
40
		// Get the application
41
		$app = JFactory::getApplication('administrator');
42
43
		// Load the User state.
44
		$name = $app->getUserState('com_localise.packagefile.name');
45
		$this->setState('packagefile.name', $name);
46
47
		$id = $app->getUserState('com_localise.edit.packagefile.id');
48
		$this->setState('packagefile.id', $id);
49
	}
50
51
	/**
52
	 * Returns a Table object, always creating it.
53
	 *
54
	 * @param   string  $type    The table type to instantiate
55
	 * @param   string  $prefix  A prefix for the table class name. Optional.
56
	 * @param   array   $config  Configuration array for model. Optional.
57
	 *
58
	 * @return  JTable  A database object
59
	 */
60
	public function getTable($type = 'Localise', $prefix = 'LocaliseTable', $config = array())
61
	{
62
		return JTable::getInstance($type, $prefix, $config);
63
	}
64
65
	/**
66
	 * Method to get the record form.
67
	 *
68
	 * @param   array    $data      Data for the form.
69
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
70
	 *
71
	 * @return  mixed  A JForm object on success, false on failure
72
	 */
73 View Code Duplication
	public function getForm($data = array(), $loadData = true)
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...
74
	{
75
		// Get the form.
76
		$id   = $this->getState('packagefile.id');
0 ignored issues
show
Unused Code introduced by
$id 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...
77
		$name = $this->getState('packagefile.name');
78
		$form = $this->loadForm('com_localise.packagefile', 'packagefile', array('control' => 'jform', 'load_data' => $loadData));
79
80
		if (empty($form))
81
		{
82
			return false;
83
		}
84
85
		$form->setFieldAttribute('translations', 'packagefile', $name, 'translations');
86
87
		// Check for an error.
88
		if (JError::isError($form))
89
		{
90
			$this->setError($form->getMessage());
91
92
			return false;
93
		}
94
95
		return $form;
96
	}
97
98
	/**
99
	 * Method to get the data that should be injected in the form.
100
	 *
101
	 * @return   mixed  The data for the form.
102
	 */
103 View Code Duplication
	protected function loadFormData()
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...
104
	{
105
		// Initialise variables.
106
		$app = JFactory::getApplication();
107
108
		// Check the session for previously entered form data.
109
		$data = $app->getUserState('com_localise.edit.packagefile.data', array());
110
111
		// Get the package data.
112
		if (empty($data))
113
		{
114
			$data = $this->getItem();
115
		}
116
117
		return $data;
118
	}
119
120
	/**
121
	 * Method to get the ftp form.
122
	 *
123
	 * @return  mixed  A JForm object on success, false on failure or not ftp
124
	 */
125 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...
126
	{
127
		// Get the form.
128
		$form = $this->loadForm('com_localise.ftp', 'ftp');
129
130
		if (empty($form))
131
		{
132
			return false;
133
		}
134
135
		// Check for an error.
136
		if (JError::isError($form))
137
		{
138
			$this->setError($form->getMessage());
139
140
			return false;
141
		}
142
143
		return $form;
144
	}
145
146
	/**
147
	 * Method to get the package.
148
	 *
149
	 * @param   integer  $pk  The ID of the primary key.
150
	 *
151
	 * @return JObject the package
152
	 */
153
	public function getItem($pk = null)
154
	{
155
		$id = $this->getState('packagefile.id');
156
		$id = is_array($id) ? (count($id) > 0 ? $id[0] : 0) : $id;
157
		$package = new JObject;
158
		$package->checked_out = 0;
159
		$package->standalone  = true;
160
		$package->manifest    = null;
161
		$package->description = null;
162
		$package->id          = $id;
163
164
		if (!empty($id))
165
		{
166
			// If the package exists get it
167
			$table = $this->getTable();
168
169
			if (is_array($id))
170
			{
171
				$id = $id[0];
172
			}
173
174
			$table->load($id);
175
			$package->setProperties($table->getProperties());
176
177
			// Get the manifest
178
			$xml = simplexml_load_file($table->path);
179
180
			if ($xml)
181
			{
182
				$manifest = (string) $xml->manifest;
183
184
				// $client   = (string) $xml->manifest->attributes()->client;
185
186
				// LocaliseHelper::loadLanguage($manifest, $client);
187
188
				// Set up basic information
189
				$name = basename($table->path);
190
				$name = substr($name, 0, strlen($name) - 4);
191
192
				$package->id          = $id;
193
				$package->name        = $name;
194
				$package->manifest    = $manifest;
195
196
				// $package->client      = $client;
197
198
				// $package->standalone  = substr($manifest, 0, 4) == 'fil_';
199
				$package->core        = ((string) $xml->attributes()->core) == 'true';
200
				$package->title       = (string) $xml->title;
201
				$package->version     = (string) $xml->version;
202
				$package->packversion = (string) $xml->packversion;
203
				$package->description = (string) $xml->description;
204
				$package->language    = (string) $xml->language;
205
				$package->license     = (string) $xml->license;
206
				$package->copyright   = (string) $xml->copyright;
207
				$package->author      = (string) $xml->author;
208
				$package->authoremail = (string) $xml->authoremail;
209
				$package->authorurl   = (string) $xml->authorurl;
210
				$package->packager    = (string) $xml->packager;
211
				$package->packagerurl = (string) $xml->packagerurl;
212
				$package->servername  = (string) $xml->servername;
213
				$package->serverurl   = (string) $xml->serverurl;
214
				$package->writable    = LocaliseHelper::isWritable($package->path);
215
216
				$user = JFactory::getUser($table->checked_out);
217
				$package->setProperties($table->getProperties());
218
219
				if ($package->checked_out == JFactory::getUser()->id)
220
				{
221
					$package->checked_out = 0;
222
				}
223
224
				$package->editor = JText::sprintf('COM_LOCALISE_TEXT_PACKAGE_EDITOR', $user->name, $user->username);
225
226
				// Get the translations
227
				$package->translations  = array();
228
				$package->administrator = array();
229
230 View Code Duplication
				if ($xml->administrator)
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...
231
				{
232
					foreach ($xml->administrator->children() as $file)
233
					{
234
						$data = (string) $file;
235
236
						if ($data)
237
						{
238
							$package->translations[] = "administrator_$data";
239
						}
240
						else
241
						{
242
							$package->translations[] = "administrator_joomla";
243
						}
244
245
						$package->administrator[] = $data;
246
					}
247
				}
248
249
				$package->site = array();
250
251 View Code Duplication
				if ($xml->site)
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...
252
				{
253
					foreach ($xml->site->children() as $file)
254
					{
255
						$data = (string) $file;
256
257
						if ($data)
258
						{
259
							$package->translations[] = "site_$data";
260
						}
261
						else
262
						{
263
							$package->translations[] = "site_joomla";
264
						}
265
266
						$package->site[] = $data;
267
					}
268
				}
269
			}
270
			else
271
			{
272
				$package = null;
273
				$this->setError(JText::sprintf('COM_LOCALISE_ERROR_PACKAGE_FILEEDIT'), $table->path);
274
			}
275
		}
276
277
		return $package;
278
	}
279
280
	/**
281
	 * Method to save data
282
	 *
283
	 * @param   array  $data  the data to save
284
	 *
285
	 * @return  boolean  success or failure
286
	 */
287
	public function save($data)
288
	{
289
		// When editing a package, find the original path
290
		$app = JFactory::getApplication('administrator');
291
		$originalId = $app->getUserState('com_localise.edit.packagefile.id');
292
		$oldpath = null;
293
294
		$originalId = is_array($originalId) && count($originalId) > 0 ?
295
						$originalId[0] : $originalId;
296
297 View Code Duplication
		if (!empty($originalId))
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...
298
		{
299
			$db = JFactory::getDbo();
300
			$query = $db->getQuery(true)
301
				->select($db->quoteName('path'))
302
				->from($db->quoteName('#__localise'))
303
				->where($db->quoteName('id') . ' = ' . $originalId);
304
			$db->setQuery($query);
305
306
			$oldpath = $db->loadResult('path');
307
		}
308
309
		// Get the package name
310
		$name = $data['name'];
311
312
		// Get the package
313
		$package  = $this->getItem();
314
		$path     = JPATH_COMPONENT_ADMINISTRATOR . "/packages/$name.xml";
315
		$manifest = $name;
316
317
		// $client   = $package->client ? $package->client : 'site';
318
319
		if ($package->standalone)
320
		{
321
			$title = $name;
322
			$description = $data['description'];
323
324
			$dom = new DOMDocument('1.0', 'utf-8');
325
326
			// Create simple XML element and base package tag
327
			$packageXml = $dom->createElement('package');
328
329
			// Add main package information
330
			$titleElement = $dom->createElement('title', $title);
331
			$descriptionElement = $dom->createElement('description', $description);
332
			$manifestElement = $dom->createElement('manifest', $manifest);
333
			$versionElement = $dom->createElement('version', $data['version']);
334
			$packversionElement = $dom->createElement('packversion', $data['packversion']);
335
			$authorElement = $dom->createElement('author', $data['author']);
336
			$licenseElement = $dom->createElement('license', $data['license']);
337
			$authorEmailElement = $dom->createElement('authoremail', $data['authoremail']);
338
			$authorUrlElement = $dom->createElement('authorurl', $data['authorurl']);
339
			$languageElement = $dom->createElement('language', $data['language']);
340
			$copyrightElement = $dom->createElement('copyright', $data['copyright']);
341
			$packagerElement = $dom->createElement('packager', $data['packager']);
342
			$packagerUrlElement = $dom->createElement('packagerurl', $data['packagerurl']);
343
			$servernameElement = $dom->createElement('servername', $data['servername']);
344
			$serverurlElement = $dom->createElement('serverurl', $data['serverurl']);
345
346
			// Set the client attribute on the manifest element
347
348
			// $clientAttribute = $dom->createAttribute('client');
349
350
			// $clientAttribute->value = $client;
351
352
			// $manifestElement->appendChild($clientAttribute);
353
354
			// Add all the elements to the parent <package> tag
355
			$packageXml->appendChild($titleElement);
356
			$packageXml->appendChild($descriptionElement);
357
			$packageXml->appendChild($manifestElement);
358
			$packageXml->appendChild($versionElement);
359
			$packageXml->appendChild($packversionElement);
360
			$packageXml->appendChild($authorElement);
361
			$packageXml->appendChild($copyrightElement);
362
			$packageXml->appendChild($licenseElement);
363
			$packageXml->appendChild($authorEmailElement);
364
			$packageXml->appendChild($authorUrlElement);
365
			$packageXml->appendChild($languageElement);
366
			$packageXml->appendChild($copyrightElement);
367
			$packageXml->appendChild($packagerElement);
368
			$packageXml->appendChild($packagerUrlElement);
369
			$packageXml->appendChild($servernameElement);
370
			$packageXml->appendChild($serverurlElement);
371
372
			$administrator = array();
373
			$site          = array();
374
375 View Code Duplication
			foreach ($data['translations'] as $translation)
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...
376
			{
377
				if (preg_match('/^site_(.*)$/', $translation, $matches))
378
				{
379
					$site[] = $matches[1];
380
				}
381
382
				if (preg_match('/^administrator_(.*)$/', $translation, $matches))
383
				{
384
					$administrator[] = $matches[1];
385
				}
386
			}
387
388
			// Add the site language files
389 View Code Duplication
			if (count($site))
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...
390
			{
391
				$siteXml = $dom->createElement('site');
392
393
				foreach ($site as $translation)
394
				{
395
					$fileElement = $dom->createElement('filename', $translation . '.ini');
396
					$siteXml->appendChild($fileElement);
397
				}
398
399
				$packageXml->appendChild($siteXml);
400
			}
401
402
			// Add the administrator language files
403 View Code Duplication
			if (count($administrator))
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...
404
			{
405
				$adminXml = $dom->createElement('administrator');
406
407
				foreach ($administrator as $translation)
408
				{
409
					$fileElement = $dom->createElement('filename', $translation . '.ini');
410
					$adminXml->appendChild($fileElement);
411
				}
412
413
				$packageXml->appendChild($adminXml);
414
			}
415
416
			$dom->appendChild($packageXml);
417
418
			// Set FTP credentials, if given.
419
			JClientHelper::setCredentialsFromRequest('ftp');
420
			$ftp = JClientHelper::getCredentials('ftp');
421
422
			// Try to make the file writeable.
423 View Code Duplication
			if (JFile::exists($path) && !$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...
424
			{
425
				$this->setError(JText::sprintf('COM_LOCALISE_ERROR_PACKAGE_WRITABLE', $path));
426
427
				return false;
428
			}
429
430
			// Make the XML look pretty
431
			$dom->formatOutput = true;
432
			$formattedXML = $dom->saveXML();
433
434
			$return = JFile::write($path, $formattedXML);
435
436
			// Try to make the file unwriteable.
437 View Code Duplication
			if (!$ftp['enabled'] && JPath::isOwner($path) && !JPath::setPermissions($path, '0444'))
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...
438
			{
439
				$this->setError(JText::sprintf('COM_LOCALISE_ERROR_PACKAGE_UNWRITABLE', $path));
440
441
				return false;
442
			}
443
			elseif (!$return)
444
			{
445
				$this->setError(JText::sprintf('COM_LOCALISE_ERROR_PACKAGE_FILESAVE', $path));
446
447
				return false;
448
			}
449
		}
450
451
		/** @TODO: Check ftp code
452
		// Save the title and the description in the language file
453
		$translation_path  = LocaliseHelper::findTranslationPath($client, JFactory::getLanguage()->getTag(), $manifest);
454
		$translation_id    = LocaliseHelper::getFileId($translation_path);
455
		$translation_model = JModelLegacy::getInstance('Translation', 'LocaliseModel', array('ignore_request' => true));
456
457
		if ($translation_model->checkout($translation_id))
458
		{
459
			$translation_model->setState('translation.path', $translation_path);
460
			$translation_model->setState('translation.client', $client);
461
			$translation = $translation_model->getItem();
462
			$sections    = LocaliseHelper::parseSections($translation_path);
463
		}
464
		else
465
		{
466
		}
467
468
		$text = '';
469
		//$text .= strtoupper($title) . '="' . str_replace('"', '"_QQ_"', $data['title']) . "\"\n";
470
		//$text .= strtoupper($description) . '="' . str_replace('"', '"_QQ_"', $data['description']) . "\"\n";
471
		//$tag  = JFactory::getLanguage()->getTag();
472
		//$languagePath = JPATH_SITE . "/language/$tag/$tag.$manifest.ini";
473
474
		// Try to make the file writeable.
475
		if (!$ftp['enabled'] && JPath::isOwner($languagePath) && !JPath::setPermissions($languagePath, '0644'))
476
		{
477
			$this->setError(JText::sprintf('COM_LOCALISE_ERROR_PACKAGE_WRITABLE', $languagePath));
478
479
			return false;
480
		}
481
482
		//$return = JFile::write($languagePath, $text);
483
484
		// Try to make the file unwriteable.
485
		if (!$ftp['enabled'] && JPath::isOwner($languagePath) && !JPath::setPermissions($languagePath, '0444'))
486
		{
487
			$this->setError(JText::sprintf('COM_LOCALISE_ERROR_PACKAGE_UNWRITABLE', $languagePath));
488
489
			return false;
490
		}
491
		elseif (!$return)
492
		{
493
			$this->setError(JText::sprintf('COM_LOCALISE_ERROR_PACKAGE_FILESAVE', $languagePath));
494
495
			return false;
496
		}
497
498
		*/
499 View Code Duplication
		if ($path == $oldpath)
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...
500
		{
501
			$id = LocaliseHelper::getFileId($path);
502
			$this->setState('packagefile.id', $id);
503
504
			// Bind the rules.
505
			$table = $this->getTable();
506
			$table->load($id);
507
		}
508
		else
509
		{
510
			$table = $this->getTable();
511
512
			if (!$table->delete((int) $originalId))
513
			{
514
				$this->setError($table->getError());
515
516
				return false;
517
			}
518
519
			$table->store();
520
521
			$id = LocaliseHelper::getFileId($path);
522
			$this->setState('packagefile.id', $id);
523
			$app->setUserState('com_localise.edit.packagefile.id', $id);
524
		}
525
526
		if (isset($data['rules']))
527
		{
528
			$rules = new JAccessRules($data['rules']);
529
			$table->setRules($rules);
530
		}
531
532
		// Check the data.
533
		if (!$table->check())
534
		{
535
			$this->setError($table->getError());
536
537
			return false;
538
		}
539
540
		// Store the data.
541
		if (!$table->store())
542
		{
543
			$this->setError($table->getError());
544
545
			return false;
546
		}
547
548
		// Delete the older file and redirect
549 View Code Duplication
		if ($path !== $oldpath && file_exists($oldpath))
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...
550
		{
551
			if (!JFile::delete($oldpath))
552
			{
553
				$app->enqueueMessage(JText::_('COM_LOCALISE_ERROR_OLDFILE_REMOVE'), 'notice');
554
			}
555
556
			$task = JFactory::getApplication()->input->get('task');
557
558
			if ($task == 'save')
559
			{
560
				$app->redirect(JRoute::_('index.php?option=com_localise&view=packages', false));
561
			}
562
			else
563
			{
564
				// Redirect to the new $id as name has changed
565
				$app->redirect(JRoute::_('index.php?option=com_localise&view=packagefile&layout=edit&id=' . $this->getState('packagefile.id'), false));
566
			}
567
		}
568
569
		$this->cleanCache();
570
571
		return true;
572
	}
573
574
	/**
575
	 * Method to generate and download a package
576
	 *
577
	 * @param   array  $data  the data to generate the package
578
	 *
579
	 * @return  boolean  success or failure
580
	 */
581
	public function download($data)
582
	{
583
		// The data could potentially be loaded from the file with $this->getItem() instead of using directly the data from the post
584
		$app = JFactory::getApplication();
585
586
		// Prevent generating and downloading Master package
587 View Code Duplication
		if (strpos($data['name'], 'master_') !== false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
588
		{
589
			$app->enqueueMessage(JText::sprintf('COM_LOCALISE_ERROR_MASTER_PACKAGE_DOWNLOAD_FORBIDDEN', $data['name']), 'warning');
590
			$app->redirect(JRoute::_('index.php?option=com_localise&view=packagefile&layout=edit&id=' . $this->getState('packagefile.id'), false));
591
592
			return false;
593
		}
594
595
		$administrator = array();
596
		$site          = array();
597
		$msg = null;
598
599
		// Delete old files
600
		$delete = JFolder::files(JPATH_ROOT . '/tmp/', 'com_localise_', false, true);
601
602 View Code Duplication
		if (!empty($delete))
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...
603
		{
604
			if (!JFile::delete($delete))
605
			{
606
				// JFile::delete throws an error
607
				$this->setError(JText::_('COM_LOCALISE_ERROR_EXPORT_ZIPDELETE'));
608
609
				return false;
610
			}
611
		}
612
613 View Code Duplication
		foreach ($data['translations'] as $translation)
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...
614
		{
615
			if (preg_match('/^site_(.*)$/', $translation, $matches))
616
			{
617
				$site[] = $matches[1];
618
			}
619
620
			if (preg_match('/^administrator_(.*)$/', $translation, $matches))
621
			{
622
				$administrator[] = $matches[1];
623
			}
624
		}
625
626
		$parts = explode('.', $data['version']);
627
		$small_version = implode('.', array($parts[0],$parts[1]));
628
629
		// Prepare text to save for the xml package description
630
		$text = '';
631
		$text .= '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
632
		$text .= '<extension type="file" version="' . $small_version . '" method="upgrade">' . "\n";
633
		$text .= "\t" . '<name>' . $data['name'] . $data['language'] . '</name>' . "\n";
634
		$text .= "\t" . '<version>' . $data['version'] . '.' . $data['packversion'] . '</version>' . "\n";
635
		$text .= "\t" . '<creationDate>' . date('d/m/Y') . '</creationDate>' . "\n";
636
		$text .= "\t" . '<author>' . $data['author'] . '</author>' . "\n";
637
		$text .= "\t" . '<authorEmail>' . $data['authoremail'] . '</authorEmail>' . "\n";
638
		$text .= "\t" . '<authorUrl>' . $data['authorurl'] . '</authorUrl>' . "\n";
639
		$text .= "\t" . '<copyright>' . $data['copyright'] . '</copyright>' . "\n";
640
		$text .= "\t" . '<license>' . $data['license'] . '</license>' . "\n";
641
		$text .= "\t" . '<packager>' . $data['packager'] . '</packager>' . "\n";
642
		$text .= "\t" . '<packagerurl>' . $data['packagerurl'] . '</packagerurl>' . "\n";
643
		$text .= "\t" . '<description><![CDATA[' . $data['description'] . ']]></description>' . "\n";
644
		$text .= "\t" . '<fileset>' . "\n";
645
646 View Code Duplication
		if (count($site))
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...
647
		{
648
			$text .= "\t\t" . '<files ';
649
			$text .= 'folder="site/' . $data['language'] . '"';
650
			$text .= ' target="language/' . $data['language'] . '">' . "\n";
651
			$site_package_files = array();
652
653
			// $site_package_zip_path = JPATH_ROOT . '/tmp/' . uniqid('com_localise_') . '.zip';
654
655
			foreach ($site as $translation)
656
			{
657
				$path = LocaliseHelper::findTranslationPath($client = 'site', $tag = $data['language'], $filename = $translation);
658
659
				if (JFile::exists($path))
660
				{
661
					$file_data = file_get_contents($path);
662
				}
663
664
				if (JFile::exists($path) && !empty($file_data))
665
				{
666
					$text .= "\t\t\t" . '<filename>' . $data['language'] . '.' . $translation . '.ini</filename>' . "\n";
667
					$site_package_files[] = array('name' => $data['language'] . '.' . $translation . '.ini','data' => $file_data);
668
				}
669
				else
670
				{
671
					$msg .= JText::sprintf('COM_LOCALISE_FILE_NOT_TRANSLATED', $data['language'] . '.' . $translation . '.ini', JText::_('JSITE'));
672
				}
673
			}
674
675
			/**
676
			$site_txt .= "\t\t".'<filename file="meta">install.xml</filename>' . "\n";
677
			$site_txt .= "\t\t".'<filename file="meta">' . $data['language'] . '.xml</filename>' . "\n";
678
			$site_txt .= "\t".'</files>' . "\n";
679
			$site_txt .= "\t".'<params />' . "\n";
680
			$site_txt .= "\t".'</extension>' . "\n";
681
			$site_package_files[] = array('name'=>'install.xml','data'=>$site_txt);
682
			$language_data = file_get_contents(JPATH_ROOT . '/language/' . $data['language'] . '/' . $data['language'] . '.xml');
683
			$site_package_files[] = array('name' => $data['language'] . '.xml','data'=>$language_data);
684
			$language_data = file_get_contents(JPATH_ROOT . '/language/' . $data['language'] . '/' . $data['language'] . '.localise.php');
685
			$site_package_files[] = array('name' => $data['language'] . '.localise.php','data' => $language_data);
686
687
			$site_zip_path = JPATH_ROOT . '/tmp/' . uniqid('com_localise_') . '.zip';
688
			if (!$packager = JArchive::getAdapter('zip'))
689
			{
690
				$this->setError(JText::_('COM_LOCALISE_ERROR_EXPORT_ADAPTER'));
691
692
				return false;
693
			}
694
			else
695
			{
696
				if (!$packager->create($site_zip_path, $site_package_files))
697
				{
698
					$this->setError(JText::_('COM_LOCALISE_ERROR_EXPORT_ZIPCREATE'));
699
700
					return false;
701
				}
702
			}
703
			*/
704
705
			$text .= "\t\t" . '</files>' . "\n";
706
707
			if ($msg)
0 ignored issues
show
Bug Best Practice introduced by
The expression $msg of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
708
			{
709
				$msg .= '<p>...</p>';
710
			}
711
712
			foreach ($site_package_files as $file)
713
			{
714
				$main_package_files[] = array('name' => 'site/' . $data['language'] . '/' . $file['name'], 'data' => $file['data']);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$main_package_files was never initialized. Although not strictly required by PHP, it is generally a good practice to add $main_package_files = 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...
715
			}
716
		}
717
718 View Code Duplication
		if (count($administrator))
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...
719
		{
720
			$text .= "\t\t" . '<files ';
721
			$text .= 'folder="admin/' . $data['language'] . '"';
722
			$text .= ' target="administrator/language/' . $data['language'] . '">' . "\n";
723
724
			$admin_package_files = array();
725
726
			foreach ($administrator as $translation)
727
			{
728
				$path = LocaliseHelper::findTranslationPath($client = 'administrator', $tag = $data['language'], $filename = $translation);
729
730
				if (JFile::exists($path))
731
				{
732
					$file_data = file_get_contents($path);
733
				}
734
735
				if (JFile::exists($path) && !empty($file_data))
736
				{
737
					$text .= "\t\t\t" . '<filename>' . $data['language'] . '.' . $translation . '.ini</filename>' . "\n";
738
					$admin_package_files[] = array('name' => $data['language'] . '.' . $translation . '.ini','data' => $file_data);
739
				}
740
				else
741
				{
742
					$msg .= JText::sprintf('COM_LOCALISE_FILE_NOT_TRANSLATED', $data['language'] . '.' . $translation . '.ini', JText::_('JADMINISTRATOR'));
743
				}
744
			}
745
746
			/**
747
			$admin_txt .= "\t\t".'<filename file="meta">install.xml</filename>' . "\n";
748
			$admin_txt .= "\t\t".'<filename file="meta">' . $data['language'].'.xml</filename>' . "\n";
749
			$admin_txt .= "\t".'</files>' . "\n";
750
			$admin_txt .= "\t".'<params />' . "\n";
751
			$admin_txt .= "\t".'</extension>' . "\n";
752
			$admin_package_files[] = array('name'=>'install.xml','data'=>$admin_txt);
753
			$language_data = file_get_contents(JPATH_ROOT . '/administrator/language/' . $data['language'] . '/' . $data['language'] . '.xml');
754
			$admin_package_files[] = array('name'=>$data['language'] . '.xml','data' => $language_data);
755
			$language_data = file_get_contents(JPATH_ROOT . '/administrator/language/' . $data['language'] . '/' . $data['language'] . '.localise.php');
756
			$admin_package_files[] = array('name'=>$data['language'] . '.localise.php','data' => $language_data);
757
758
759
			$admin_zip_path = JPATH_ROOT . '/tmp/' . uniqid('com_localise_') . '.zip';
760
			if (!$packager = JArchive::getAdapter('zip'))
761
			{
762
				$this->setError(JText::_('COM_LOCALISE_ERROR_EXPORT_ADAPTER'));
763
764
				return false;
765
			}
766
			else
767
			{
768
				if (!$packager->create($admin_zip_path, $admin_package_files))
769
				{
770
					$this->setError(JText::_('COM_LOCALISE_ERROR_EXPORT_ZIPCREATE'));
771
772
					return false;
773
				}
774
			}
775
			*/
776
			$text .= "\t\t" . '</files>' . "\n";
777
778
			foreach ($admin_package_files as $file)
779
			{
780
				$main_package_files[] = array('name' => 'admin/' . $data['language'] . '/' . $file['name'], 'data' => $file['data']);
0 ignored issues
show
Bug introduced by
The variable $main_package_files 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...
781
			}
782
		}
783
784 View Code Duplication
		if ($msg)
0 ignored issues
show
Bug Best Practice introduced by
The expression $msg of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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...
785
		{
786
			$msg .= '<p>...</p>';
787
			$msg .= JText::_('COM_LOCALISE_UNTRANSLATED');
788
			$app->enqueueMessage($msg, 'error');
789
			$app->redirect(JRoute::_('index.php?option=com_localise&view=packagefile&layout=edit&id=' . $this->getState('packagefile.id'), false));
790
791
			return false;
792
		}
793
794
		$text .= "\t" . '</fileset>' . "\n";
795
796 View Code Duplication
		if (!empty($data['serverurl']))
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...
797
		{
798
			$text .= "\t" . '<updateservers>' . "\n";
799
			$text .= "\t\t" . '<server type="collection" priority="1" name="' . $data['servername'] . '">' . $data['serverurl'] . '</server>' . "\n";
800
			$text .= "\t" . '</updateservers>' . "\n";
801
		}
802
803
		$text .= '</extension>' . "\n";
804
805
		$main_package_files[] = array('name' => $data['name'] . $data['language'] . '.xml', 'data' => $text);
806
807
		$ziproot = JPATH_ROOT . '/tmp/' . uniqid('com_localise_main_') . '.zip';
808
809
		// Run the packager
810 View Code Duplication
		if (!$packager = JArchive::getAdapter('zip'))
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...
811
		{
812
			$this->setError(JText::_('COM_LOCALISE_ERROR_EXPORT_ADAPTER'));
813
814
			return false;
815
		}
816
		else
817
		{
818
			if (!$packager->create($ziproot, $main_package_files))
819
			{
820
				$this->setError(JText::_('COM_LOCALISE_ERROR_EXPORT_ZIPCREATE'));
821
822
				return false;
823
			}
824
		}
825
826
		ob_clean();
827
		$zipdata = file_get_contents($ziproot);
828
		header("Expires: 0");
829
		header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
830
		header('Content-Type: application/zip');
831
		header('Content-Disposition: attachment; filename="'
832
				. $data['name'] . '_' . $data['language'] . '_' . $data['version'] . 'v' . $data['packversion'] . '.zip"');
833
		header('Content-Length: ' . strlen($zipdata));
834
		header("Cache-Control: maxage=1");
835
		header("Pragma: public");
836
		header("Content-Transfer-Encoding: binary");
837
		echo $zipdata;
838
		exit;
839
	}
840
}
841