Passed
Pull Request — develop (#892)
by Tito
04:56
created

RTranslationHelper::renderTranslationModal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
c 0
b 0
f 0
dl 0
loc 17
rs 9.7998
cc 1
nc 1
nop 4
1
<?php
2
/**
3
 * @package     Redcore
4
 * @subpackage  Translation
5
 *
6
 * @copyright   Copyright (C) 2008 - 2020 redWEB.dk. All rights reserved.
7
 * @license     GNU General Public License version 2 or later, see LICENSE.
8
 */
9
10
use Joomla\CMS\Document\HtmlDocument;
0 ignored issues
show
Bug introduced by
The type Joomla\CMS\Document\HtmlDocument was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Joomla\CMS\Factory;
0 ignored issues
show
Bug introduced by
The type Joomla\CMS\Factory was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Joomla\CMS\Router\Router;
0 ignored issues
show
Bug introduced by
The type Joomla\CMS\Router\Router was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Joomla\CMS\Uri\Uri;
0 ignored issues
show
Bug introduced by
The type Joomla\CMS\Uri\Uri was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
15
defined('_JEXEC') or die;
16
17
jimport('joomla.filesystem.folder');
18
19
/**
20
 * A Translation helper.
21
 *
22
 * @package     Redcore
23
 * @subpackage  Translation
24
 * @since       1.0
25
 */
26
class RTranslationHelper
27
{
28
	/**
29
	 * Defines if jQuery Migrate should be loaded in Frontend component/modules
30
	 *
31
	 * @var    JRegistry
0 ignored issues
show
Bug introduced by
The type JRegistry was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
	 */
33
	public static $pluginParams = null;
34
35
	/**
36
	 * Default language
37
	 *
38
	 * @var    array
39
	 * @since  1.0
40
	 */
41
	public static $siteLanguage = null;
42
43
	/**
44
	 * Include paths for searching for Params classes.
45
	 *
46
	 * @var    array
47
	 * @since  1.0
48
	 */
49
	public static $includePaths = array();
50
51
	/**
52
	 * Constructor
53
	 */
54
	public function __construct()
55
	{
56
		self::$pluginParams = new JRegistry;
57
	}
58
59
	/**
60
	 * Get default language
61
	 *
62
	 * @param   string  $client  Name of the client to get (site|admin)
63
	 *
64
	 * @return  string  Name of the language ex. en-GB
65
	 */
66
	public static function getSiteLanguage($client = 'site')
67
	{
68
		if (!isset(self::$siteLanguage))
69
		{
70
			$db           = JFactory::getDbo();
71
			$oldTranslate = $db->translate;
72
73
			// We do not want to translate this value
74
			$db->translate = false;
75
76
			self::$siteLanguage = JComponentHelper::getParams('com_languages')->get($client);
77
78
			// We put translation check back on
79
			$db->translate = $oldTranslate;
80
		}
81
82
		return self::$siteLanguage;
83
	}
84
85
	/**
86
	 * Get list of all translation tables with columns. It is here for backward compatibility below version 1.8.3
87
	 *
88
	 * @return  array  Array or table with columns columns
89
	 */
90
	public static function getInstalledTranslationTables()
91
	{
92
		return RTranslationTable::getInstalledTranslationTables();
93
	}
94
95
	/**
96
	 * Checks if this is edit form and restricts table from translations
97
	 *
98
	 * @param   array  $translationTables  List of translation tables
99
	 *
100
	 * @return  array  Array or table with columns columns
101
	 */
102
	public static function removeFromEditForm($translationTables)
103
	{
104
		$input  = JFactory::getApplication()->input;
105
		$option = $input->getString('option', '');
106
		$view   = $input->getString('view', '');
107
		$layout = $input->getString('layout', '');
108
		$task   = $input->getString('layout', '');
109
110
		if ($layout == 'edit' || $task == 'edit')
111
		{
112
			foreach ($translationTables as $tableKey => $translationTable)
113
			{
114
				if (!empty($translationTable->formLinks))
115
				{
116
					foreach ($translationTable->formLinks as $formLink)
117
					{
118
						$id = $input->getString($formLink['identifier'], '');
119
120
						if ($option == $formLink['option'] && $view == $formLink['view'] && $layout == $formLink['layout'] && $id)
121
						{
122
							unset($translationTables[$tableKey]);
123
							break;
124
						}
125
					}
126
				}
127
			}
128
		}
129
130
		return $translationTables;
131
	}
132
133
	/**
134
	 * Add a filesystem path where Translation system should search for Params files.
135
	 * You may either pass a string or an array of paths.
136
	 *
137
	 * @param   mixed  $path  A filesystem path or array of filesystem paths to add.
138
	 *
139
	 * @return  array  An array of filesystem paths to find Params in.
140
	 *
141
	 * @since   1.0
142
	 */
143
	public static function addIncludePath($path = null)
144
	{
145
		// Convert the passed path(s) to add to an array.
146
		settype($path, 'array');
147
148
		// If we have new paths to add, do so.
149
		if (!empty($path))
150
		{
151
			// Check and add each individual new path.
152
			foreach ($path as $dir)
153
			{
154
				// Sanitize path.
155
				$dir = trim($dir);
156
157
				// Add to the front of the list so that custom paths are searched first.
158
				if (!in_array($dir, self::$includePaths))
159
				{
160
					array_unshift(self::$includePaths, $dir);
161
				}
162
			}
163
		}
164
165
		return self::$includePaths;
166
	}
167
168
	/**
169
	 * Loads form for Params field
170
	 *
171
	 * @param   array                       $column            Content element column
172
	 * @param   RTranslationContentElement  $translationTable  Translation table
173
	 * @param   mixed                       $data              The data expected for the form.
174
	 * @param   string                      $controlName       Name of the form control group
175
	 * @param   string                      $basepath          Base path to use when loading files
176
	 *
177
	 * @return  array  Array or table with columns columns
178
	 */
179
	public static function loadParamsForm($column, $translationTable, $data, $controlName = '', $basepath = JPATH_BASE)
180
	{
181
		if (version_compare(JVERSION, '3.0', '<') && !empty($column['formname25']))
182
		{
183
			$formName = !empty($column['formname']) ? $column['formname25'] : $column['name'];
184
		}
185
		else
186
		{
187
			$formName = !empty($column['formname']) ? $column['formname'] : $column['name'];
188
		}
189
190
		// Handle the optional arguments.
191
		$options              = array();
192
		$options['control']   = $controlName;
193
		$options['load_data'] = true;
194
		$formData             = array();
195
196
		if (!empty($data->{$column['name']}))
197
		{
198
			$registry = new JRegistry;
199
			$registry->loadString($data->{$column['name']});
200
			$formData[$column['name']] = $registry->toArray();
201
		}
202
203
		// Load common and local language files.
204
		$lang = JFactory::getLanguage();
205
206
		// Load language file
207
		$lang->load($translationTable->extension_name, $basepath, null, false, false)
0 ignored issues
show
Bug introduced by
The property extension_name does not exist on RTranslationContentElement. Did you mean extension?
Loading history...
208
		|| $lang->load($translationTable->extension_name, $basepath . "/components/" . $translationTable->extension_name, null, false, false)
209
		|| $lang->load($translationTable->extension_name, $basepath, $lang->getDefault(), false, false)
210
		|| $lang->load(
211
			$translationTable->extension_name, $basepath . "/components/" . $translationTable->extension_name, $lang->getDefault(), false, false
212
		);
213
214
		// Get the form.
215
		RForm::addFormPath($basepath . '/components/' . $translationTable->extension_name . '/models/forms');
216
		RForm::addFormPath($basepath . '/administrator/components/' . $translationTable->extension_name . '/models/forms');
217
		RForm::addFieldPath($basepath . '/components/' . $translationTable->extension_name . '/models/fields');
218
		RForm::addFieldPath($basepath . '/administrator/components/' . $translationTable->extension_name . '/models/fields');
219
220
		if (!empty($column['formpath']))
221
		{
222
			RForm::addFormPath($basepath . $column['formpath']);
223
		}
224
225
		if (!empty($column['fieldpath']))
226
		{
227
			RForm::addFieldPath($basepath . $column['fieldpath']);
228
		}
229
230
		$xpath = !empty($column['xpath']) ? $column['xpath'] : false;
231
232
		try
233
		{
234
			$form = RForm::getInstance('com_redcore.params_' . $column['name'] . $controlName, $formName, $options, false, $xpath);
235
236
			// Allow for additional modification of the form, and events to be triggered.
237
			// We pass the data because plugins may require it.
238
			self::preprocessForm($form, $data, 'content', $column, $translationTable);
0 ignored issues
show
Bug introduced by
$translationTable of type RTranslationContentElement is incompatible with the type RedcoreTableTranslation_Table expected by parameter $translationTable of RTranslationHelper::preprocessForm(). ( Ignorable by Annotation )

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

238
			self::preprocessForm($form, $data, 'content', $column, /** @scrutinizer ignore-type */ $translationTable);
Loading history...
239
240
			// Load the data into the form after the plugins have operated.
241
			$form->bind($formData);
242
		}
243
		catch (Exception $e)
244
		{
245
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
246
		}
247
248
		if (empty($form))
249
		{
250
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
251
		}
252
253
		return $form;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $form returns the type RForm which is incompatible with the documented return type array.
Loading history...
254
	}
255
256
	/**
257
	 * Method to allow derived classes to preprocess the form.
258
	 *
259
	 * @param   JForm                          $form              A JForm object.
260
	 * @param   mixed                          $data              The data expected for the form.
261
	 * @param   string                         $group             The name of the plugin group to import (defaults to "content").
262
	 * @param   array                          $column            Content element column
263
	 * @param   RedcoreTableTranslation_Table  $translationTable  Translation table
264
	 *
265
	 * @return  void
266
	 *
267
	 * @see     JFormField
268
	 * @since   12.2
269
	 * @throws  Exception if there is an error in the form event.
270
	 */
271
	public static function preprocessForm(JForm $form, $data, $group = 'content', $column = array(), $translationTable = null)
0 ignored issues
show
Unused Code introduced by
The parameter $column is not used and could be removed. ( Ignorable by Annotation )

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

271
	public static function preprocessForm(JForm $form, $data, $group = 'content', /** @scrutinizer ignore-unused */ $column = array(), $translationTable = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
272
	{
273
		$tableName = str_replace('#__', '', $translationTable->name);
274
275
		if ($tableName == 'modules')
276
		{
277
			$form = self::preprocessFormModules($form, $data);
278
		}
279
		elseif ($tableName == 'menus')
280
		{
281
			$form = self::preprocessFormMenu($form, $data);
282
		}
283
		elseif ($tableName == 'plugins')
284
		{
285
			$form = self::preprocessFormPlugins($form, $data);
286
		}
287
288
		// Import the appropriate plugin group.
289
		JPluginHelper::importPlugin($group);
290
291
		// Get the dispatcher.
292
		$dispatcher = RFactory::getDispatcher();
293
294
		// Trigger the form preparation event.
295
		$results = $dispatcher->trigger('onContentPrepareForm', array($form, $data));
296
297
		// Check for errors encountered while preparing the form.
298
		if (count($results) && in_array(false, $results, true))
299
		{
300
			// Get the last error.
301
			$error = $dispatcher->getError();
0 ignored issues
show
Deprecated Code introduced by
The function JObject::getError() has been deprecated: 12.3 JError has been deprecated ( Ignorable by Annotation )

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

301
			$error = /** @scrutinizer ignore-deprecated */ $dispatcher->getError();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
302
303
			if (!($error instanceof Exception))
0 ignored issues
show
introduced by
$error is never a sub-type of Exception.
Loading history...
304
			{
305
				throw new Exception($error);
306
			}
307
		}
308
	}
309
310
	/**
311
	 * Method to preprocess the form for modules
312
	 *
313
	 * @param   JForm  $form  A form object.
314
	 * @param   mixed  $data  The data expected for the form.
315
	 *
316
	 * @return  JForm
317
	 *
318
	 * @since   1.6
319
	 * @throws  Exception if there is an error loading the form.
320
	 */
321
	public static function preprocessFormModules(JForm $form, $data)
322
	{
323
		jimport('joomla.filesystem.path');
324
325
		$lang     = JFactory::getLanguage();
326
		$clientId = $data->client_id;
327
		$module   = $data->module;
328
329
		$client   = JApplicationHelper::getClientInfo($clientId);
330
		$formFile = JPath::clean($client->path . '/modules/' . $module . '/' . $module . '.xml');
331
332
		// Load the core and/or local language file(s).
333
		$lang->load($module, $client->path, null, false, true)
334
		||	$lang->load($module, $client->path . '/modules/' . $module, null, false, true);
335
336
		if (file_exists($formFile))
337
		{
338
			// Get the module form.
339
			if (!$form->loadFile($formFile, false, '//config'))
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $reset of JForm::loadFile(). ( Ignorable by Annotation )

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

339
			if (!$form->loadFile($formFile, /** @scrutinizer ignore-type */ false, '//config'))
Loading history...
340
			{
341
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
342
			}
343
		}
344
345
		return $form;
346
	}
347
348
	/**
349
	 * Method to preprocess the form for plugins
350
	 *
351
	 * @param   JForm  $form  A form object.
352
	 * @param   mixed  $data  The data expected for the form.
353
	 *
354
	 * @return  JForm
355
	 *
356
	 * @since   1.6
357
	 * @throws  Exception if there is an error loading the form.
358
	 */
359
	public static function preprocessFormPlugins(JForm $form, $data)
360
	{
361
		jimport('joomla.filesystem.path');
362
363
		$lang      = JFactory::getLanguage();
364
		$extension = 'plg_' . $data->folder . '_' . $data->element;
365
366
		$formFile = JPath::clean(JPATH_PLUGINS . '/' . $data->folder . '/' . $data->element . '/' . $data->element . '.xml');
367
368
		// Load the core and/or local language file(s).
369
		$lang->load(strtolower($extension), JPATH_ADMINISTRATOR, null, false, true)
370
			|| $lang->load(strtolower($extension), JPATH_PLUGINS . '/' . $data->folder . '/' . $data->element, null, false, true);
371
		$lang->load(strtolower($extension . '.sys'), JPATH_ADMINISTRATOR, null, false, true)
372
			|| $lang->load(strtolower($extension . '.sys'), JPATH_PLUGINS . '/' . $data->folder . '/' . $data->element, null, false, true);
373
374
		if (file_exists($formFile))
375
		{
376
			// Get the module form.
377
			if (!$form->loadFile($formFile, false, '//config'))
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $reset of JForm::loadFile(). ( Ignorable by Annotation )

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

377
			if (!$form->loadFile($formFile, /** @scrutinizer ignore-type */ false, '//config'))
Loading history...
378
			{
379
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
380
			}
381
		}
382
383
		return $form;
384
	}
385
386
	/**
387
	 * Method to preprocess the form for modules
388
	 *
389
	 * @param   JForm  $form  A form object.
390
	 * @param   mixed  $data  The data expected for the form.
391
	 *
392
	 * @return  JForm
393
	 *
394
	 * @since   1.6
395
	 * @throws  Exception if there is an error loading the form.
396
	 */
397
	public static function preprocessFormMenu(JForm $form, $data)
398
	{
399
		jimport('joomla.filesystem.path');
400
		$link     = $data->link;
401
		$type     = $data->type;
402
		$formFile = false;
403
404
		// Initialise form with component view params if available.
405
		if ($type == 'component')
406
		{
407
			$link = htmlspecialchars_decode($link);
408
409
			// Parse the link arguments.
410
			$args = array();
411
			parse_str(parse_url(htmlspecialchars_decode($link), PHP_URL_QUERY), $args);
412
413
			// Confirm that the option is defined.
414
			$option = '';
415
			$base   = '';
416
417
			if (isset($args['option']))
418
			{
419
				// The option determines the base path to work with.
420
				$option = $args['option'];
421
				$base   = JPATH_SITE . '/components/' . $option;
422
			}
423
424
			// Confirm a view is defined.
425
			$formFile = false;
426
427
			if (isset($args['view']))
428
			{
429
				$view = $args['view'];
430
431
				// Determine the layout to search for.
432
				if (isset($args['layout']))
433
				{
434
					$layout = $args['layout'];
435
				}
436
				else
437
				{
438
					$layout = 'default';
439
				}
440
441
				$formFile = false;
442
443
				// Check for the layout XML file. Use standard xml file if it exists.
444
				$tplFolders = array(
445
					$base . '/views/' . $view . '/tmpl',
446
					$base . '/view/' . $view . '/tmpl'
447
				);
448
				$path       = JPath::find($tplFolders, $layout . '.xml');
449
450
				if (is_file($path))
0 ignored issues
show
Bug introduced by
It seems like $path can also be of type false; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

450
				if (is_file(/** @scrutinizer ignore-type */ $path))
Loading history...
451
				{
452
					$formFile = $path;
453
				}
454
455
				// If custom layout, get the xml file from the template folder
456
				// template folder is first part of file name -- template:folder
457
				if (!$formFile && (strpos($layout, ':') > 0))
458
				{
459
					$temp         = explode(':', $layout);
460
					$templatePath = JPATH::clean(JPATH_SITE . '/templates/' . $temp[0] . '/html/' . $option . '/' . $view . '/' . $temp[1] . '.xml');
461
462
					if (is_file($templatePath))
463
					{
464
						$formFile = $templatePath;
465
					}
466
				}
467
			}
468
469
			// Now check for a view manifest file
470
			if (!$formFile)
471
			{
472
				if (isset($view))
473
				{
474
					$metadataFolders = array(
475
						$base . '/view/' . $view,
476
						$base . '/views/' . $view
477
					);
478
					$metaPath        = JPath::find($metadataFolders, 'metadata.xml');
479
480
					if (is_file($path = JPath::clean($metaPath)))
0 ignored issues
show
Bug introduced by
It seems like $metaPath can also be of type false; however, parameter $path of JPath::clean() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

480
					if (is_file($path = JPath::clean(/** @scrutinizer ignore-type */ $metaPath)))
Loading history...
481
					{
482
						$formFile = $path;
483
					}
484
				}
485
				else
486
				{
487
					// Now check for a component manifest file
488
					$path = JPath::clean($base . '/metadata.xml');
489
490
					if (is_file($path))
491
					{
492
						$formFile = $path;
493
					}
494
				}
495
			}
496
497
			$lang = JFactory::getLanguage();
498
			$lang->load($option, JPATH_BASE, null, false, false)
499
			|| $lang->load($option, JPATH_BASE . "/components/" . $option, null, false, false)
500
			|| $lang->load($option, JPATH_BASE, $lang->getDefault(), false, false)
501
			|| $lang->load($option, JPATH_BASE . "/components/" . $option, $lang->getDefault(), false, false);
502
		}
503
504
		if ($formFile)
505
		{
506
			// If an XML file was found in the component, load it first.
507
			// We need to qualify the full path to avoid collisions with component file names.
508
509
			if ($form->loadFile($formFile, true, '/metadata') == false)
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $reset of JForm::loadFile(). ( Ignorable by Annotation )

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

509
			if ($form->loadFile($formFile, /** @scrutinizer ignore-type */ true, '/metadata') == false)
Loading history...
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

Loading history...
510
			{
511
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
512
			}
513
		}
514
515
		// Now load the component params.
516
		// TODO: Work out why 'fixing' this breaks JForm
517
		if ($isNew = false)
0 ignored issues
show
Unused Code introduced by
The assignment to $isNew is dead and can be removed.
Loading history...
518
		{
519
			$path = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $option . '/config.xml');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $option does not seem to be defined for all execution paths leading up to this point.
Loading history...
520
		}
521
		else
522
		{
523
			$path = 'null';
524
		}
525
526
		if (is_file($path))
527
		{
528
			// Add the component params last of all to the existing form.
529
			if (!$form->load($path, true, '/config'))
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $replace of JForm::load(). ( Ignorable by Annotation )

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

529
			if (!$form->load($path, /** @scrutinizer ignore-type */ true, '/config'))
Loading history...
530
			{
531
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
532
			}
533
		}
534
535
		// Load the specific type file
536
		if (!$form->loadFile('item_' . $type, false, false))
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $xpath of JForm::loadFile(). ( Ignorable by Annotation )

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

536
		if (!$form->loadFile('item_' . $type, false, /** @scrutinizer ignore-type */ false))
Loading history...
Bug introduced by
false of type false is incompatible with the type string expected by parameter $reset of JForm::loadFile(). ( Ignorable by Annotation )

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

536
		if (!$form->loadFile('item_' . $type, /** @scrutinizer ignore-type */ false, false))
Loading history...
537
		{
538
			throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
539
		}
540
541
		return $form;
542
	}
543
544
	/**
545
	 * Method to reset plugin translation keys
546
	 *
547
	 * @return  void
548
	 */
549
	public static function resetPluginTranslation()
550
	{
551
		$user   = JFactory::getUser();
552
		$levels = implode(',', $user->getAuthorisedViewLevels());
553
554
		$db    = JFactory::getDbo();
555
		$query = $db->getQuery(true)
556
			->select('folder AS type, element AS name, params')
557
			->from('#__extensions')
558
			->where('enabled = 1')
559
			->where('type =' . $db->quote('plugin'))
560
			->where('state IN (0,1)')
561
			->where('access IN (' . $levels . ')')
562
			->order('ordering');
563
564
		$plugins = $db->setQuery($query)->loadObjectList();
565
566
		foreach ($plugins as $plugin)
567
		{
568
			$joomlaPlugin         = JPluginHelper::getPlugin($plugin->type, $plugin->name);
569
			$joomlaPlugin->params = $plugin->params;
570
		}
571
	}
572
573
	/**
574
	 * Method to check if the current application instance is an administrator instance
575
	 * and that this is not an API call.
576
	 *
577
	 * @return bool true if this is admin and is not an API call
578
	 *
579
	 * @throws Exception
580
	 */
581
	public static function isAdmin()
582
	{
583
		$app   = JFactory::getApplication();
584
		$isApi = ($app->input->get('api') != null);
585
586
		return ((version_compare(JVERSION, '3.7', '<') ? $app->isAdmin() : $app->isClient('administrator')) && !$isApi);
0 ignored issues
show
Deprecated Code introduced by
The function JApplicationCms::isAdmin() has been deprecated: Use isClient('administrator') instead. ( Ignorable by Annotation )

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

586
		return ((version_compare(JVERSION, '3.7', '<') ? /** @scrutinizer ignore-deprecated */ $app->isAdmin() : $app->isClient('administrator')) && !$isApi);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
587
	}
588
589
	/**
590
	 * Checks to see if the language exists and then load it
591
	 *
592
	 * @param   string  $language      Language name
593
	 * @param   bool    $loadLanguage  Loads the language if it exists
594
	 *
595
	 * @return  boolean  Returns true if language exists and we have switched to new language
596
	 */
597
	public static  function setLanguage($language, $loadLanguage = true)
598
	{
599
		$languages    = JLanguageHelper::getLanguages('sef');
600
		$languageKeys = explode('-', $language);
601
602
		if (!empty($languageKeys[0]) && !empty($languages[$languageKeys[0]]->lang_code))
603
		{
604
			JFactory::getApplication()->input->set('lang', $language);
605
			$languageObject = new JLanguage($languages[$languageKeys[0]]->lang_code);
606
607
			if ($loadLanguage)
608
			{
609
				$languageObject->load();
610
			}
611
612
			return true;
613
		}
614
615
		return false;
616
	}
617
618
	/**
619
	 * Checks if the current page is a translatable form.
620
	 *
621
	 * @param   bool  $isAdmin  Informs us whether we are on frontend or backend
622
	 *
623
	 * @return  void
624
	 */
625
	public static function isTranslatableForm($isAdmin)
626
	{
627
		// Current page values
628
		$input  = JFactory::getApplication()->input;
629
		$option = $input->getString('option', '');
630
		$view   = $input->getString('view', '');
631
		$layout = $input->getString('layout', '');
632
		$task   = $input->getString('task', '');
0 ignored issues
show
Unused Code introduced by
The assignment to $task is dead and can be removed.
Loading history...
633
634
		$translationTables = self::getInstalledTranslationTables();
635
636
		foreach ($translationTables as $tableKey => $translationTable)
637
		{
638
			if (!isset($translationTable->formLinks))
639
			{
640
				continue;
641
			}
642
643
			foreach ($translationTable->formLinks as $formLink)
644
			{
645
				// Form values
646
				$tableAdmin     = !empty($formLink['admin']) ? $formLink['admin'] : 'false';
647
				$tableOption    = $formLink['option'];
648
				$tableView      = $formLink['view'];
649
				$tableLayout    = !empty($formLink['layout']) ? $formLink['layout'] : 'edit';
650
				$tableID        = isset($formLink['identifier']) ? $formLink['identifier'] : 'id';
651
				$showButton     = !empty($formLink['showbutton']) ? $formLink['showbutton'] : 'true';
652
				$htmlposition   = !empty($formLink['htmlposition']) ? $formLink['htmlposition'] : '.btn-toolbar:first';
653
				$checkPrimaryId = !empty($formLink['checkoriginalid']) ? $formLink['checkoriginalid'] : 'false';
654
				$results        = null;
655
656
				// Check if the form's frontend/backend options matches the current page
657
				$tableAdmin = $tableAdmin === 'true' ? true : false;
658
659
				if ($isAdmin != $tableAdmin)
660
				{
661
					continue;
662
				}
663
664
				// Check whether form values matches the current page
665
				if ($option == $tableOption && $view == $tableView && $layout == $tableLayout)
666
				{
667
					// Get id of item based on the form identifier.
668
					$itemID = $input->getInt($tableID, '');
669
670
					// If the item doesn't have an ID, tell the user that they have to save the item first.
671
					if (empty($itemID))
672
					{
673
						self::renderTranslationModal(false, false, false, false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $htmlposition of RTranslationHelper::renderTranslationModal(). ( Ignorable by Annotation )

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

673
						self::renderTranslationModal(false, false, false, /** @scrutinizer ignore-type */ false);
Loading history...
Bug introduced by
false of type false is incompatible with the type array expected by parameter $linkname of RTranslationHelper::renderTranslationModal(). ( Ignorable by Annotation )

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

673
						self::renderTranslationModal(false, /** @scrutinizer ignore-type */ false, false, false);
Loading history...
Bug introduced by
false of type false is incompatible with the type string expected by parameter $itemID of RTranslationHelper::renderTranslationModal(). ( Ignorable by Annotation )

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

673
						self::renderTranslationModal(/** @scrutinizer ignore-type */ false, false, false, false);
Loading history...
Bug introduced by
false of type false is incompatible with the type integer expected by parameter $contentelement of RTranslationHelper::renderTranslationModal(). ( Ignorable by Annotation )

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

673
						self::renderTranslationModal(false, false, /** @scrutinizer ignore-type */ false, false);
Loading history...
674
675
						return;
676
					}
677
678
					if ($checkPrimaryId == 'true')
679
					{
680
						// Check whether there's a relation between the current item and the translation element
681
						$db    = JFactory::getDbo();
682
						$query = $db->getQuery(true)
683
							->select($db->qn($translationTable->primaryKeys[0]))
684
							->from($db->qn($translationTable->table))
685
							->where($db->qn($translationTable->primaryKeys[0]) . '=' . $db->q($itemID));
686
687
						$db->setQuery($query);
688
						$results = $db->loadObjectList();
689
690
						$checkPrimaryId = !empty($results) ? 'false' : 'true';
691
					}
692
693
					// If there is, render a modal button & window in the toolbar
694
					if ($checkPrimaryId == 'false' && $showButton == 'true')
695
					{
696
						$linkname       = JText::_('LIB_REDCORE_TRANSLATION_NAME_BUTTON') . ' ' . $translationTable->title;
697
						$contentelement = str_replace('#__', '', $translationTable->table);
698
699
						self::renderTranslationModal($itemID, $linkname, $contentelement, $htmlposition);
0 ignored issues
show
Bug introduced by
$linkname of type string is incompatible with the type array expected by parameter $linkname of RTranslationHelper::renderTranslationModal(). ( Ignorable by Annotation )

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

699
						self::renderTranslationModal($itemID, /** @scrutinizer ignore-type */ $linkname, $contentelement, $htmlposition);
Loading history...
700
					}
701
				}
702
			}
703
		}
704
	}
705
706
	/**
707
	 * Renders a modal button & window for a translation element
708
	 *
709
	 * @param   string  $itemID          The id of the current item being shown
710
	 * @param   array   $linkname        The text to be shown on the modal button
711
	 * @param   int     $contentelement  The current translation element
712
	 * @param   string  $htmlposition    The position on the page where the button should be moved to
713
	 *
714
	 * @return  void
715
	 */
716
	public static function renderTranslationModal($itemID, $linkname, $contentelement, $htmlposition)
717
	{
718
		echo RLayoutHelper::render(
719
			'modal.iframe-full-page',
720
			array(
0 ignored issues
show
Bug introduced by
array('id' => $itemID, '...tion' => $htmlposition) of type array<string,array|integer|string> is incompatible with the type object expected by parameter $displayData of RLayoutHelper::render(). ( Ignorable by Annotation )

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

720
			/** @scrutinizer ignore-type */ array(
Loading history...
721
				'id' => $itemID,
722
				'header' => '',
723
				'linkName' => $linkname,
724
				'link' => JRoute::_('index.php?option=com_redcore&view=translation&task=translation.display&layout=modal-edit&translationTableName='
725
									. $contentelement
726
									. '&id='
727
									. $itemID
728
					. '&tmpl=component'
729
				),
730
				'linkClass' => 'btn btn-primary',
731
				'contentElement' => $contentelement,
732
				'htmlposition' => $htmlposition,
733
			)
734
		);
735
	}
736
737
	/**
738
	 * Gets translation item status
739
	 *
740
	 * @param   object  $item     Translate item object
741
	 * @param   array   $columns  List of columns used in translation
742
	 *
743
	 * @return  string  Translation Item status
744
	 */
745
	public static function getTranslationItemStatus($item, $columns)
746
	{
747
		if (empty($item->rctranslations_language))
748
		{
749
			return array('badge' => 'label label-danger', 'status' => 'JNONE');
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('badge' => ...', 'status' => 'JNONE') returns the type array<string,string> which is incompatible with the documented return type string.
Loading history...
750
		}
751
		elseif ($item->rctranslations_state != 1)
752
		{
753
			return array('badge' => 'label label-danger', 'status' => 'JUNPUBLISHED');
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('badge' => ...tus' => 'JUNPUBLISHED') returns the type array<string,string> which is incompatible with the documented return type string.
Loading history...
754
		}
755
		else
756
		{
757
			$originalValues = new JRegistry;
758
759
			if (is_array($item->rctranslations_originals))
760
			{
761
				$originalValues->loadArray($item->rctranslations_originals);
762
			}
763
			else
764
			{
765
				$originalValues->loadString((string) $item->rctranslations_originals);
766
			}
767
768
			$translationStatus = array('badge' => 'label label-success', 'status' => 'COM_REDCORE_TRANSLATIONS_STATUS_TRANSLATED');
769
770
			foreach ($columns as $column)
771
			{
772
				if (md5($item->$column) != $originalValues->get($column))
773
				{
774
					$translationStatus = array('badge' => 'label label-warning', 'status' => 'COM_REDCORE_TRANSLATIONS_STATUS_CHANGED');
775
					break;
776
				}
777
			}
778
779
			return $translationStatus;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $translationStatus returns the type array<string,string> which is incompatible with the documented return type string.
Loading history...
780
		}
781
	}
782
783
	/**
784
	 * Gets translation item id and returns it
785
	 *
786
	 * @param   int     $itemid                Item id
787
	 * @param   string  $langCode              Language code
788
	 * @param   string  $pk                    Primary key name
789
	 * @param   string  $translationTableName  Name of the translation table
790
	 *
791
	 * @return  int     Translations item id
792
	 */
793
	public static function getTranslationItemId($itemid, $langCode, $pk, $translationTableName)
794
	{
795
		$ids = explode('###', $itemid);
796
797
		$db    = JFactory::getDbo();
798
		$query = $db->getQuery(true)
799
			->select('rctranslations_id')
800
			->from($db->qn(RTranslationTable::getTranslationsTableName($translationTableName, '#__')))
801
			->where('rctranslations_language=' . $db->q($langCode));
802
803
		foreach ($pk as $key => $primaryKey)
0 ignored issues
show
Bug introduced by
The expression $pk of type string is not traversable.
Loading history...
804
		{
805
			$query->where($db->qn($primaryKey) . ' = ' . $db->q($ids[$key]));
806
		}
807
808
		$db->setQuery($query);
809
810
		$result = $db->loadResult();
811
812
		return $result;
813
	}
814
815
	/**
816
	 * Checks if an array of data has any data
817
	 *
818
	 * @param   array  $data      Array of data to be checked
819
	 * @param   array  $excludes  Array of keys to be excluded from validation
820
	 *
821
	 * @return  boolean  True if the array contains data
822
	 */
823
	public static function validateEmptyTranslationData($data, $excludes = null)
824
	{
825
		// Remove excluded keys from array
826
		foreach ($excludes as $exclude)
827
		{
828
			unset($data[$exclude]);
829
		}
830
831
		// Check if the rest of the keys in the array are empty
832
		if (array_filter($data, 'strlen'))
833
		{
834
			return true;
835
		}
836
		else
837
		{
838
			return false;
839
		}
840
	}
841
842
	/**
843
	 * Adds array to a JForm input
844
	 *
845
	 * @param   string  $form   Form to be modified
846
	 * @param   string  $index  Index of the array
847
	 *
848
	 * @return  string  Modified form
849
	 */
850
	public static function arrayifyTranslationJForm($form, $index)
851
	{
852
		$pattern     = '/name="jform/';
853
		$replacement = 'name="jform[' . $index . ']';
854
		$form        = preg_replace($pattern, $replacement, $form);
855
856
		return $form;
857
	}
858
859
	/**
860
	 * Returns an array of all content language codes (fx. en-GB)
861
	 *
862
	 * @return array  All content language codes
863
	 */
864
	public static function getAllContentLanguageCodes()
865
	{
866
		$contentLanguages = JLanguageHelper::getLanguages();
867
868
		$languageCodes = array();
869
870
		foreach ($contentLanguages as $language)
871
		{
872
			$languageCodes[] = $language->lang_code;
873
		}
874
875
		return $languageCodes;
876
	}
877
878
	/**
879
	 * Add alternate link to the <head>
880
	 *
881
	 * @return void
882
	 */
883
	public static function addAlternateLinks()
884
	{
885
		/** @var HtmlDocument $doc */
886
		$doc       = Factory::getDocument();
887
		$languages = JLanguageHelper::getLanguages();
888
		$app       = Factory::getApplication();
889
890
		if (!RBootstrap::getConfig('enable_translations', 0)
891
			|| !RBootstrap::getConfig('translations_alternate_meta', 0)
892
			|| $app->isClient('administrator')
893
			|| php_sapi_name() === 'cli'
894
			|| $doc->getType() !== 'html'
895
			|| count($languages) < 2)
896
		{
897
			return;
898
		}
899
900
		$uri = new Uri(Uri::getInstance()->toString());
901
902
		if (Factory::getConfig()->get('sef'))
903
		{
904
			$router = clone Router::getInstance('site');
905
			$router->setVars([], false);
906
			$uri->setQuery(
907
				array_merge(
908
					$router->parse($uri),
909
					$uri->getQuery(true)
910
				)
911
			);
912
		}
913
914
		$uri->delVar('Itemid');
915
916
		foreach ($languages as $language)
917
		{
918
			$uri->setVar('lang', $language->lang_code);
919
			$route = RRoute::_(
920
				'index.php' . $uri->toString(['path', 'query', 'fragment']),
921
				true, null, true
922
			);
923
924
			// Use a custom tag because addHeadLink is limited to one URI per tag
925
			$doc->addCustomTag(
926
				'<link href="' . $route . '" rel="alternate" hreflang="' . $language->sef . '" />'
927
			)->addCustomTag(
928
				'<link href="' . $route . '" rel="alternate" hreflang="' . $language->lang_code . '" />'
929
			);
930
		}
931
	}
932
}
933