getLastRelevantOverlayLanguageId()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace AOE\Languagevisibility\Services;
4
5
/***************************************************************
6
 * Copyright notice
7
 *
8
 * (c) 2016 AOE GmbH <[email protected]>
9
 * All rights reserved
10
 *
11
 * This script is part of the TYPO3 project. The TYPO3 project is
12
 * free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * The GNU General Public License can be found at
18
 * http://www.gnu.org/copyleft/gpl.html.
19
 *
20
 * This script is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * This copyright notice MUST APPEAR in all copies of the script!
26
 ***************************************************************/
27
28
use AOE\Languagevisibility\CacheManager;
29
use AOE\Languagevisibility\Element;
30
use AOE\Languagevisibility\Language;
31
use AOE\Languagevisibility\PageElement;
32
use AOE\Languagevisibility\Visibility;
33
use TYPO3\CMS\Core\Utility\GeneralUtility;
34
35
/**
36
 *
37
 * @author	Daniel Poetzinger <[email protected]>
38
 * @coauthor Tolleiv Nietsch <[email protected]>
39
 * @coauthor Timo Schmidt <[email protected]>
40
 */
41
class VisibilityService {
42
43
	/**
44
	 * @var boolean holds the state if inheritance is enabled or not
45
	 */
46
	protected static $useInheritance;
47
48
	/**
49
	 * @var array
50
	 */
51
	private static $supportedTables;
52
53
	/**
54
	 * Constructor of the service, used to initialize the service with the usage of the inheritance feature.
55
	 */
56
	public function __construct() {
57
		if (!isset(self::$useInheritance)) {
58
			$confArr = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['languagevisibility']);
59
			if (is_array($confArr) && $confArr['inheritanceEnabled']) {
60
				self::setUseInheritance();
61
			} else {
62
				self::setUseInheritance(false);
63
			}
64
		}
65
	}
66
67
	/**
68
	 * This method returns the configuration of the inheritance flag. If an inheritance flag is set
69
	 * this method can be used to read it.
70
	 *
71
	 * @return boolean
72
	 */
73
	public static function getUseInheritance() {
74
		return self::$useInheritance;
75
	}
76
77
	/**
78
	 * Function to configure the visibilityService to use inherited settings.
79
	 *
80
	 * @param boolean $useInheritance
81
	 */
82
	public static function setUseInheritance($useInheritance = TRUE) {
83
		self::$useInheritance = $useInheritance;
84
	}
85
86
	/**
87
	 * returns relevant languageid for overlay record or FALSE if element is not visible for guven language
88
	 *
89
	 * @param \AOE\Languagevisibility\Language $language
90
	 * @param \AOE\Languagevisibility\Element $element
91
	 * @return mixed
92
	 */
93
	function getOverlayLanguageIdForLanguageAndElement(Language $language, Element $element) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
94
		if ($this->isVisible($language, $element)) {
95
			return $this->_relevantOverlayLanguageId;
0 ignored issues
show
Bug introduced by
The property _relevantOverlayLanguageId does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
96
		} else {
97
			return FALSE;
98
		}
99
	}
100
101
	/**
102
	 * currently used to get correct r
103
	 * page rootline - also if a page in rootline is not vivible
104
	 *
105
	 * @todo can this resolved diffrent? the relevantOverlayLanguageId is set in isVisible
106
	 * @return int
107
	 */
108
	public function getLastRelevantOverlayLanguageId() {
109
		return $this->_relevantOverlayLanguageId;
110
	}
111
112
	/**
113
	 * Gets the tables configured with language visibility support.
114
	 *
115
	 * @static
116
	 * @return array with all supported tables
117
	 */
118
	public static function getSupportedTables() {
119
		if (!isset(self::$supportedTables)) {
120
			self::$supportedTables = array('pages', 'tt_content', 'tt_news', 'pages_language_overlay');
121
122
			if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['getElementForTable'])
123
				&& is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['getElementForTable'])
124
			) {
125
				self::$supportedTables = array_merge(
126
					self::$supportedTables,
127
					array_keys($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['getElementForTable'])
128
				);
129
			}
130
131
			if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['recordElementSupportedTables'])
132
				&& is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['recordElementSupportedTables'])
133
			) {
134
				self::$supportedTables = array_merge(
135
					self::$supportedTables,
136
					array_keys($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['recordElementSupportedTables'])
137
				);
138
			}
139
		}
140
141
		return self::$supportedTables;
142
	}
143
144
	/**
145
	 * Returns true or FALSE wether the element is visible in the certain language.
146
	 * (sets for internal access only $this->_relevantOverlayLanguageId which holds the overlay languageid)
147
	 *
148
	 * @param \AOE\Languagevisibility\Language $language
149
	 * @param \AOE\Languagevisibility\Element $element
150
	 * @param bool $omitLocal
151
	 * @throws \Exception
152
	 * @return boolean
153
	 */
154
	public function isVisible(Language $language, Element $element, $omitLocal = FALSE) {
155
		$this->_relevantOverlayLanguageId = $language->getUid();
156
		$languageRepository = GeneralUtility::makeInstance('AOE\\Languagevisibility\\LanguageRepository');
157
158
		$visibility = $this->getVisibilitySetting($language, $element, $omitLocal);
159
		if ($visibility == 'yes') {
160
			if (!$element->hasTranslation($language->getUid())) {
161
				$this->_relevantOverlayLanguageId = 0;
162
			}
163
			$result = TRUE;
164
		} elseif ($visibility == 'no+') {
165
			$result = FALSE;
166
		} elseif ($visibility == 'no') {
167
			$result = FALSE;
168
		} elseif ($visibility == 't') {
169
			if ($element->hasTranslation($language->getUid())) {
170
				$result = TRUE;
171
			} else {
172
				$result = FALSE;
173
			}
174
		} elseif ($visibility == 'f') {
175
			if ($element->hasTranslation($language->getUid())) {
176
				$result = TRUE;
177
			} else {
178
				$result = FALSE;
179
180
					// there is no direct translation for this element, therefore check languages in fallback
181
				$fallBackOrder = $element->getFallbackOrder($language);
182
				if (!is_array($fallBackOrder)) {
183
					throw new \Exception(print_r($element, TRUE));
184
				}
185
186
				foreach ($fallBackOrder as $languageid) {
187
					$fallbackLanguage = $languageRepository->getLanguageById($languageid);
188
					if ($element->hasTranslation($languageid) && $this->isVisible($fallbackLanguage, $element, $omitLocal)) {
189
						$this->_relevantOverlayLanguageId = $languageid;
190
						$result = TRUE;
191
						break;
192
					}
193
				}
194
			}
195
		} else {
196
				// no setting or default:
197
			if ($language->getUid() == '0') {
198
				$result = TRUE;
199
			} else {
200
				$result = FALSE;
201
			}
202
		}
203
		return $result;
204
	}
205
206
	/**
207
	 * This method is used to get all bequeathing elements of an element (makes only sence for pages)
208
	 * it checks if there is any element in the rootline which has any inherited visibility setting (like no+, yes+)  as configured visibility.
209
	 *
210
	 * @param \AOE\Languagevisibility\Language $language
211
	 * @param \AOE\Languagevisibility\Element $element
212
	 *
213
	 * @return \AOE\Languagevisibility\Visibility $visibility
214
	 */
215
	protected function getInheritedVisibility(Language $language, Element $element) {
216
217
		$dao = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\Dao\\DaoCommon');
218
		$elementfactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('AOE\\Languagevisibility\\ElementFactory', $dao);
219
		$elements = $elementfactory->getParentElementsFromElement($element, $language);
220
221
		if (is_array($elements) && count($elements) > 0) {
222
			foreach ($elements as $element) {
223
				/* @var $element PageElement */
224
				$visibility = new Visibility();
225
				$visibility->setVisibilityString($element->getLocalVisibilitySetting($language->getUid()));
226
					// is the setting a inheritable setting:
227
				if ($visibility->getVisibilityString() == 'no+' || $visibility->getVisibilityString() == 'yes+') {
228
					$visibility->setVisibilityDescription('inherited from uid ' . $element->getUid());
229
					return $visibility;
230
				}
231
			}
232
		}
233
234
		if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['getInheritedVisibility'])) {
235
			foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['getInheritedVisibility'] as $classRef) {
236
				$hookObj = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classRef);
237
				if (method_exists($hookObj, 'getInheritedVisibility')) {
238
					$visibility = $hookObj->getInheritedVisibility($language, $elements, $element);
239
					if (substr($visibility->getVisibilityString(), -1) == '+') {
240
						return $visibility;
241
					}
242
				}
243
			}
244
		}
245
246
		$visibility = new Visibility();
247
		$visibility->setVisibilityString('-');
248
249
		return $visibility;
250
	}
251
252
	/**
253
	 * return the accumulated visibility setting: reads default for language then reads local for element and merges them.
254
	 * if local is default, then the global is used or it is forced to be "yes" if the language was set to all.
255
	 * if the element itself is a translated original record the element is only visible in the specific language
256
	 * If nothing is set the hardcoded default "t" (translated) is returned
257
	 *
258
	 * @param \AOE\Languagevisibility\Language $language
259
	 * @param \AOE\Languagevisibility\Element $element
260
	 * @param boolean
261
	 *
262
	 * @return string
263
	 */
264
	public function getVisibilitySetting(Language $language, Element $element, $omitLocal = FALSE) {
265
		$cacheManager = CacheManager::getInstance();
266
		$cacheData = $cacheManager->get('visibilitySettingCache');
267
		$isCacheEnabled = $cacheManager->isCacheEnabled();
268
269
		$elementTable = $element->getTable();
270
		$elementUid = $element->getUid();
271
		$languageUid = $language->getUid();
272
273
		$cacheKey = $languageUid . '_' . $elementUid . '_' . $elementTable . '_' . $omitLocal;
274
		if (!$isCacheEnabled || !isset($cacheData[$cacheKey])) {
275
			$cacheData[$cacheKey] = $this->getVisibility($language, $element, $omitLocal)->getVisibilityString();
276
			$cacheManager->set('visibilitySettingCache', $cacheData);
277
		}
278
279
		return $cacheData[$cacheKey];
280
	}
281
282
	/**
283
	 * This method can be used to retrieve an informal description for the visibility of an element
284
	 *
285
	 * @param \AOE\Languagevisibility\Language $language
286
	 * @param \AOE\Languagevisibility\Element $element
287
	 * @return string
288
	 */
289
	public function getVisibilityDescription(Language $language, Element $element) {
290
		return $this->getVisibility($language, $element)->getVisibilityDescription();
291
	}
292
293
	/**
294
	 * Create a visiblity object for an element for a given language.
295
	 * @param \AOE\Languagevisibility\Language $language
296
	 * @param \AOE\Languagevisibility\Element $element
297
	 * @param boolean $omitLocal
298
	 *
299
	 * @return \AOE\Languagevisibility\Visibility
300
	 */
301
	protected function getVisibility(Language $language, Element $element, $omitLocal = FALSE) {
302
		$visibility = new Visibility();
303
		$local = $element->getLocalVisibilitySetting($language->getUid());
304
305
		if (!$omitLocal && ($local != '' && $local != '-')) {
306
			$visibility->setVisibilityString($local)->setVisibilityDescription('local setting ' . $local);
307
			return $visibility;
308
		} else {
309
			if ($element->isLanguageSetToAll()) {
310
				$visibility->setVisibilityString('yes')->setVisibilityDescription('language configured to all');
311
				return $visibility;
312
			}
313
314
			if ($element->isMonolithicTranslated()) {
315
				if ($element->languageEquals($language)) {
316
					$visibility->setVisibilityString('yes')->setVisibilityDescription('');
317
				} else {
318
					$visibility->setVisibilityString('no')->setVisibilityDescription('');
319
				}
320
321
				return $visibility;
322
			}
323
324
			if ($element->getFieldToUseForDefaultVisibility() == 'page') {
325
				if ($this->getUseInheritance()) {
326
						// gibt es in der rootline das visibiklitysetting no+ für die sprache dann return 'no'
327
					$inheritedVisibility = $this->getInheritedVisibility($language, $element);
328
329
					switch ($inheritedVisibility->getVisibilityString()) {
330
						case 'no+' :
331
								// if no+ is found it means the current element should be threated as if it has no set
332
							$visibility->setVisibilityString('no')->setVisibilityDescription('force to no (' . $inheritedVisibility->getVisibilityDescription() . ')');
333
							break;
334
						case 'yes+' :
335
							$visibility->setVisibilityString('yes')->setVisibilityDescription('force to yes (' . $inheritedVisibility->getVisibilityDescription() . ')');
336
							break;
337
						default :
338
							$setting = $language->getDefaultVisibilityForPage($element);
339
							$visibility->setVisibilityString($setting)->setVisibilityDescription('default visibility  for page (' . $setting . ')');
340
							break;
341
					}
342
				} else {
343
						// inheritance is disabled
344
					$setting = $language->getDefaultVisibilityForPage($element);
345
					$visibility->setVisibilityString($setting)->setVisibilityDescription('default visibility  for page (' . $setting . ')');
346
				}
347
			} elseif ($element->getFieldToUseForDefaultVisibility() == 'tt_news') {
348
				$setting = $language->getDefaultVisibilityForTTNewsElement($element);
349
				$visibility->setVisibilityString($setting)->setVisibilityDescription('default visibility  for news (' . $setting . ')');
0 ignored issues
show
Documentation introduced by
$setting is of type boolean, but the function expects a string.

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...
350
			} else {
351
				$setting = $language->getDefaultVisibilityForElement($element);
352
				$visibility->setVisibilityString($setting)->setVisibilityDescription('default visibility  for element (' . $setting . ')');
353
			}
354
355
			if ($visibility->getVisibilityString() == '') {
356
				$visibility->setVisibilityString('t')->setVisibilityDescription('no visibility configured using default setting "t"');
357
			}
358
359
			return $visibility;
360
		}
361
	}
362
}
363