BeServices::getAvailableOptionsForLanguage()   F
last analyzed

Complexity

Conditions 17
Paths 304

Size

Total Lines 76
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 76
rs 3.9636
c 0
b 0
f 0
cc 17
eloc 45
nc 304
nop 3

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
namespace AOE\Languagevisibility\Services;
4
use AOE\Languagevisibility\CacheManager;
5
use AOE\Languagevisibility\Language;
6
use AOE\Languagevisibility\LanguageRepository;
7
8
/***************************************************************
9
 * Copyright notice
10
 *
11
 * (c) 2016 AOE GmbH <[email protected]>
12
 * All rights reserved
13
 *
14
 * This script is part of the TYPO3 project. The TYPO3 project is
15
 * free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * The GNU General Public License can be found at
21
 * http://www.gnu.org/copyleft/gpl.html.
22
 *
23
 * This script is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU General Public License for more details.
27
 *
28
 * This copyright notice MUST APPEAR in all copies of the script!
29
 ***************************************************************/
30
31
class BeServices extends AbstractServices {
32
33
	protected static $cache_canBeUserCopyDelete = array();
34
35
	protected static $visibleFlagsCache = array();
36
37
	protected static $cache_isVisible = array();
38
39
	/**
40
	 *
41
	 * @param $uid
42
	 * @param $table
43
	 * @return string
44
	 */
45
	public static function getVisibleFlagsForElement($uid, $table) {
46
		$cacheKey = $uid . ':' . $table;
47
48
		$cacheManager = CacheManager::getInstance();
49
		$isCacheEnabled = $cacheManager->isCacheEnabled();
50
		$cacheData = $cacheManager->get('visibleFlagsCache');
51
52
		if (! $isCacheEnabled || ! isset($cacheData[$cacheKey])) {
53
54
			$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
55
			$elementfactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\ElementFactory', $dao);
56
			try {
57
				$element = $elementfactory->getElementForTable($table, $uid);
58
			} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class AOE\Languagevisibility\Services\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

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

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

Loading history...
59
				return '-';
60
			}
61
62
			$languageRep = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\LanguageRepository');
63
			$languageList = $languageRep->getLanguages();
64
65
			$visibility = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Services\\VisibilityService');
66
67
			$visibleFlags = array();
68
			foreach ( $languageList as $language ) {
69
				if ($visibility->isVisible($language, $element)) {
70
					$visibleFlags[] = $language->getFlagImg(0);
71
				}
72
			}
73
74
			$cacheData[$cacheKey] = implode('', $visibleFlags);
75
			$cacheManager->set('visibleFlagsCache', $cacheData);
76
		}
77
78
		return $cacheData[$cacheKey];
79
	}
80
81
	/**
82
	 * Helper function to get an element by uid and tablename.
83
	 *
84
	 * @param int $uid
85
	 * @param string $table
86
	 * @param boolean $overlay_ids
87
	 * @return tx_languagevisibility_element
88
	 */
89
	public static function getElement($uid, $table, $overlay_ids = TRUE) {
90
		$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
91
		$elementfactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\ElementFactory', $dao);
92
		$element = $elementfactory->getElementForTable($table, $uid, $overlay_ids);
93
94
		return $element;
95
	}
96
97
	/**
98
	 * Helper function to check i an element with a given uid and tablename is visible for a languageid.
99
	 *
100
	 * @param int $uid
101
	 * @param string $table
102
	 * @param int $languageUid
103
	 * @param bool $omitLocal
104
	 * @return boolean
105
	 */
106
	public static function isVisible($uid, $table, $languageUid, $omitLocal = FALSE) {
107
108
		$cacheKey = sprintf('%s:%d:%d:%d', $table, $uid, $languageUid, $omitLocal);
109
110
		if (!isset(self::$cache_isVisible[$cacheKey])) {
111
112
			$rep = LanguageRepository::makeInstance();
113
			$language = $rep->getLanguageById($languageUid);
114
115
			$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
116
			$elementfactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\ElementFactory', $dao);
117
118
			try {
119
				$element = $elementfactory->getElementForTable($table, $uid);
120
			} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class AOE\Languagevisibility\Services\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

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

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

Loading history...
121
				return FALSE;
122
			}
123
124
			$visibility = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Services\\VisibilityService');
125
126
			self::$cache_isVisible[$cacheKey] = $visibility->isVisible($language, $element, $omitLocal);
127
		}
128
129
		return self::$cache_isVisible[$cacheKey];
130
	}
131
132
	/**
133
	 * Helper function to check if the current backend user has rights to cut,copy or delete
134
	 *
135
	 * @return boolean
136
	 */
137
	public static function canCurrrentUserCutCopyMoveDelete() {
138
			//current element is no overlay -> if user has rights to cutMoveDelete or is an admin don't filter commants
139
		/** @var $beUser tx_languagevisibility_beUser */
140
		$beUser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\BeUser');
141
		$userId = $beUser->getUid();
142
143
		if (!isset(self::$cache_canBeUserCopyDelete[$userId])) {
144
			if ($beUser->allowCutCopyMoveDelete() || $beUser->isAdmin()) {
145
				$result = TRUE;
146
			} else {
147
				$result = FALSE;
148
			}
149
150
			self::$cache_canBeUserCopyDelete[$userId] = $result;
151
		}
152
153
		return self::$cache_canBeUserCopyDelete[$userId];
154
	}
155
156
	/**
157
	 * Helper function to check if a record from a given table in an overlayrecord
158
	 *
159
	 * @param array $row
160
	 * @param string $table
161
	 * @return boolean
162
	 */
163
	public static function isOverlayRecord($row, $table) {
164
165
		$result = FALSE;
166
167
		switch ($table) {
168
			case 'pages_language_overlay' :
169
				$result = TRUE;
170
				break;
171
			case 'pages' :
172
				$result = FALSE;
173
				break;
174
			default:
175
176
				if (in_array($table, VisibilityService::getSupportedTables())) {
177
					$tanslationIdField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
178
					if ($tanslationIdField != '') {
179
							// if the field which points to the orginal of the translation is
180
							// not 0 a translation exists and we have an overlay record
181
						$result = $row[$tanslationIdField] != 0;
182
					}
183
				}
184
185
				break;
186
		}
187
188
		return $result;
189
	}
190
191
	/**
192
	 * Static service method to determine if an record has a translation in any language
193
	 *
194
	 * @param int $uid
195
	 * @param string $table
196
	 * @return boolean.
0 ignored issues
show
Documentation introduced by
The doc-type boolean. could not be parsed: Unknown type name "boolean." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
197
	 */
198
	public static function hasTranslationInAnyLanguage($uid, $table) {
199
		$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
200
		$elementfactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\ElementFactory', $dao);
201
202
		try {
203
			$element = $elementfactory->getElementForTable($table, $uid);
204
			$rep = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\LanguageRepository');
205
			$languages = $rep->getLanguages();
206
207
			foreach ( $languages as $language ) {
208
					//skip default language
209
				if ($language->getUid() != 0) {
210
					if ($element->hasTranslation($language->getUid())) {
211
						return TRUE;
212
					}
213
				}
214
			}
215
		} catch ( UnexpectedValueException $e ) {
0 ignored issues
show
Bug introduced by
The class AOE\Languagevisibility\S...nexpectedValueException does not exist. Did you forget a USE statement, or did you not list all dependencies?

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

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

Loading history...
216
				//the element can not be handeld by language visibility
217
			return FALSE;
218
		}
219
		return FALSE;
220
	}
221
222
	/**
223
	 * Check if given element has traslation in given language
224
	 *
225
	 * @param int $elementUid
226
	 * @param string $table
227
	 * @param int $languageUid
228
	 * @return boolean
229
	 */
230
	public static function hasTranslation($elementUid, $table, $languageUid) {
231
		$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
232
		$elementfactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\ElementFactory', $dao);
233
234
		$result = FALSE;
235
		try {
236
			$element = $elementfactory->getElementForTable($table, $elementUid);
237
			$result = $element->hasTranslation($languageUid);
238
239
		} catch ( UnexpectedValueException $e ) {
0 ignored issues
show
Bug introduced by
The class AOE\Languagevisibility\S...nexpectedValueException does not exist. Did you forget a USE statement, or did you not list all dependencies?

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

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

Loading history...
240
				//the element can not be handeld by language visibility
241
			$result = FALSE;
242
		}
243
244
		return $result;
245
	}
246
247
	/**
248
	 * checks if the current BE_USER has access to the page record:
249
	 * that is the case if:
250
	 * a) new page created -> always because then the languagevisibility is set to never for all languages where the user has no access
251
	 * b) edit page record: only if the record is only visible in languages where the user has access to
252
	 * b.1) also if the languages taht are visibile and falls back to allowed languages
253
	 * c) delete: same as for edit (only if user has access to all visible languages)
254
	 */
255
	public static function hasUserAccessToPageRecord($id, $cmd = 'edit') {
256
		if ($cmd == 'new') {
257
			return TRUE;
258
		}
259
		if (!is_numeric($id)) {
260
			return FALSE;
261
		}
262
		$rep = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\LanguageRepository');
263
		$languages = $rep->getLanguages();
264
		foreach ( $languages as $language ) {
265
			if (self::isVisible($id, 'pages', $language->getUid())) {
266
				if (!$GLOBALS['BE_USER']->checkLanguageAccess($language->getUid())) {
267
						//no access to a visible language: check fallbacks
268
					$isInFallback = FALSE;
269
					$fallbacks = $language->getFallbackOrder(self::getContextElement('pages', $id));
270
					foreach ($fallbacks as $lId) {
271
						if ($GLOBALS['BE_USER']->checkLanguageAccess($lId)) {
272
							$isInFallback = TRUE;
273
							continue;
274
						}
275
					}
276
					if (!$isInFallback) {
277
						return FALSE;
278
					}
279
				}
280
			}
281
		}
282
		return TRUE;
283
	}
284
285
	/**
286
	 * checks if the current BE_USER has access to a record:
287
	 * that is the case if:
288
	 * a) new page created -> always because then the languagevisibility is set to never for all languages where the user has no access
289
	 * b) edit page record: only if the record is only visible in languages where the user has access to
290
	 */
291
	public static function hasUserAccessToEditRecord($table, $id) {
292
		if (!is_numeric($id)) {
293
			return FALSE;
294
		}
295
		if (!self::isSupportedTable($table)) {
296
			return TRUE;
297
		}
298
299
			// check if overlay record:
300
		$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
301
		$row = $dao->getRecord($id, $table);
302
303
			// @TODO check TCA for languagefield
304
		if (self::isOverlayRecord($row, $table)) {
305
306
			if ($GLOBALS['BE_USER']->checkLanguageAccess($row['sys_language_uid'])) {
307
				return TRUE;
308
			} else {
309
				return FALSE;
310
			}
311
		}
312
313
		$rep = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\LanguageRepository');
314
		$languages = $rep->getLanguages();
315
		foreach ($languages as $language) {
316
			if (self::isVisible($id, $table, $language->getUid())) {
317
				if (!$GLOBALS['BE_USER']->checkLanguageAccess($language->getUid())) {
318
						// no access to a visible language: check fallbacks
319
					$isInFallback = FALSE;
320
					$fallbacks = $language->getFallbackOrder(self::getContextElement($table, $id));
321
					foreach ($fallbacks as $lId) {
322
						if ($GLOBALS['BE_USER']->checkLanguageAccess($lId)) {
323
								// TODO - write testcase - this can't be right
324
							$isInFallback = TRUE;
325
							continue;
326
						}
327
					}
328
					if (!$isInFallback) {
329
						return FALSE;
330
					}
331
				}
332
			}
333
		}
334
		return TRUE;
335
	}
336
337
	/**
338
	 * @param string $table
339
	 * @param int $id
340
	 * @return string
341
	 */
342
	protected function getContextElement($table, $id) {
343
		$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
344
		$elementfactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\ElementFactory', $dao);
345
		try {
346
			$element = $elementfactory->getElementForTable($table, $id);
347
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class AOE\Languagevisibility\Services\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

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

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

Loading history...
348
			return '-';
349
		}
350
		return $element;
351
	}
352
353
354
	/**
355
	 * Method to check if the inheritance is enabled or not
356
	 *
357
	 * @return boolean
358
	 */
359
	protected function isInheritanceEnabled() {
360
		$confArr = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['languagevisibility']);
361
		if (is_array($confArr)) {
362
			return ($confArr['inheritanceEnabled'] == 1);
363
		} else {
364
			return FALSE;
365
		}
366
	}
367
368
	/**
369
	 * Method to check if the inheritance is enabled or not
370
	 *
371
	 * @return boolean
372
	 */
373
	protected function isTranslatedAsDefaultEnabled() {
374
		$confArr = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['languagevisibility']);
375
		if (is_array($confArr)) {
376
			return ($confArr['translatedAsDefaultEnabled'] == 1);
377
		} else {
378
			return FALSE;
379
		}
380
	}
381
382
	/**
383
	 * returns array with the visibility options that are allowed for the current user.
384
	 *
385
	 * @param tx_languagevisibility_language $language
386
	 * @param bool $isOverlay
387
	 * @param null $element
388
	 * @return array
389
	 */
390
	public static function getAvailableOptionsForLanguage(Language $language, $isOverlay = FALSE, $element = NULL) {
391
392
		$element = $element === NULL ? self::getContextElement('pages', self::_guessCurrentPid()) : $element;
0 ignored issues
show
Documentation introduced by
self::_guessCurrentPid() is of type null|array|string, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
393
394
		$elementSupportsInheritance = $element->supportsInheritance();
0 ignored issues
show
Bug introduced by
The method supportsInheritance cannot be called on $element (of type string|null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
395
396
		$uid = $language->getUid();
397
		$select = array();
398
		$useInheritance = ($elementSupportsInheritance && self::isInheritanceEnabled());
399
400
		if (! $isOverlay) {
401
			if ($uid == 0) {
402
				$select['-'] = '-';
403
				$select['yes'] = 'yes';
404
				$select['no'] = 'no';
405
				if ($useInheritance) {
406
					$select['no+'] = 'no+';
407
				}
408
			} else {
409
				$select['-'] = '-';
410
				$select['yes'] = 'yes';
411
				$select['no'] = 'no';
412
				if ($useInheritance) {
413
					$select['no+'] = 'no+';
414
				}
415
				$select['t'] = 't';
416
				$select['f'] = 'f';
417
			}
418
419
				//check permissions, if user has no permission only no for the language is allowed
420
				// if the user has permissions for languages that act as fallbacklanguage: then the languages that falls back can have "-" in the options!
421
			if (! $GLOBALS['BE_USER']->checkLanguageAccess($uid)) {
422
423
					//check if the language falls back to one of the languages the user has permissions:
424
				$isInFallback = FALSE;
425
				$fallbacks = $language->getFallbackOrder($element);
0 ignored issues
show
Documentation introduced by
$element is of type string|null, but the function expects a object<AOE\Languagevisibility\Element>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
426
				foreach ( $fallbacks as $lId ) {
427
					if ($GLOBALS['BE_USER']->checkLanguageAccess($lId)) {
428
						$isInFallback = TRUE;
429
						continue;
430
					}
431
				}
432
				$select = array();
433
				if ($isInFallback) {
434
					$select['-'] = '-';
435
				}
436
437
				if ($uid != 0 && self::isTranslatedAsDefaultEnabled()) {
438
					$select['t'] = 't';
439
				}
440
				$select['no'] = 'no';
441
				if ($useInheritance) {
442
					$select['no+'] = 'no+';
443
				}
444
			}
445
		} else {
446
				//overlays elements can only have "force to no" or "force to no inherited"
447
			$select['-'] = '-';
448
			$select['no'] = 'no';
449
			if ($useInheritance) {
450
				$select['no+'] = 'no+';
451
			}
452
		}
453
454
		/**
455
		 * Get translations of labels from the locallang file
456
		 */
457
		if (is_object($GLOBALS['LANG'])) {
458
				//get value from locallang:
459
			foreach ( $select as $k => $v ) {
460
				$select[$k] = $GLOBALS['LANG']->sl('LLL:EXT:languagevisibility/locallang_db.xml:tx_languagevisibility_visibility.I.' . $v);
461
			}
462
		}
463
464
		return $select;
465
	}
466
467
	/**
468
	 * @return mixed
469
	 */
470
	protected static function _guessCurrentPid() {
471
		return \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id');
472
	}
473
474
	/**
475
	 * This method is used to create an visibility array with the default settings
476
	 * for all languages.
477
	 *
478
	 * @return array
479
	 */
480
	public static function getDefaultVisibilityArray() {
481
		/* @var $languageRep \\AOE\\Languagevisibility\\LanguageRepository */
482
		$languageRep = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\LanguageRepository');
483
		$languageList = $languageRep->getLanguages();
484
		$default = array();
485
		foreach ( $languageList as $language ) {
486
			$options = self::getAvailableOptionsForLanguage($language);
487
			$default[$language->getUid()] = array_shift(array_keys($options));
0 ignored issues
show
Bug introduced by
array_keys($options) cannot be passed to array_shift() as the parameter $array expects a reference.
Loading history...
488
489
		}
490
		return $default;
491
	}
492
493
	/**
494
	 * This method is used to get the table where original elements of the
495
	 * given table are stored.
496
	 *
497
	 * @param string $table
498
	 * @return string
499
	 */
500
	public static function getOriginalTableOfTranslation($table) {
501
		$translationTable = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'];
502
		if ($translationTable != '') {
503
			return $translationTable;
504
		} else {
505
			return $table;
506
		}
507
	}
508
509
	/**
510
	 * This method is used to determine the original uid of a translation
511
	 *
512
	 * @param array $row
513
	 * @param string $table
514
	 * @return string
515
	 */
516
	public static function getOriginalUidOfTranslation($row, $table) {
517
		if (is_array($row) && is_array($GLOBALS['TCA'])) {
518
			return $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']];
519
		} else {
520
			return 0;
521
		}
522
	}
523
}
524