Completed
Push — master ( 17598f...0cca5d )
by Tim
14:26
created

Classes/Xclass/ContentObjectRenderer.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * ContentObjectRenderer
4
 */
5
6
namespace FRUIT\Popup\Xclass;
7
8
use TYPO3\CMS\Core\Utility\GeneralUtility;
9
use TYPO3\CMS\Core\Utility\HttpUtility;
10
use TYPO3\CMS\Core\Utility\MathUtility;
11
use TYPO3\CMS\Frontend\Http\UrlProcessorInterface;
12
use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
13
use TYPO3\CMS\Frontend\Page\PageRepository;
14
15
/**
16
 * ContentObjectRenderer
17
 */
18
class ContentObjectRenderer extends \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
19
{
20
21
    /**
22
     * Implements the "typolink" property of stdWrap (and others)
23
     * Basically the input string, $linktext, is (typically) wrapped in a <a>-tag linking to some page, email address, file or URL based on a parameter defined by the configuration array $conf.
24
     * This function is best used from internal functions as is. There are some API functions defined after this function which is more suited for general usage in external applications.
25
     * Generally the concept "typolink" should be used in your own applications as an API for making links to pages with parameters and more. The reason for this is that you will then automatically make links compatible with all the centralized functions for URL simulation and manipulation of parameters into hashes and more.
26
     * For many more details on the parameters and how they are interpreted, please see the link to TSref below.
27
     *
28
     * the FAL API is handled with the namespace/prefix "file:..."
29
     *
30
     * @param string $linktxt The string (text) to link
31
     * @param array  $conf    TypoScript configuration (see link below)
32
     *
33
     * @return string A link-wrapped string.
34
     * @see stdWrap(), \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_linkTP()
35
     */
36
    public function typoLink($linktxt, $conf)
37
    {
38
        $linktxt = (string)$linktxt;
39
        $tsfe = $this->getTypoScriptFrontendController();
40
41
        $LD = array();
42
        $finalTagParts = array();
43
        $finalTagParts['aTagParams'] = $this->getATagParams($conf);
44
        $linkParameter = trim(isset($conf['parameter.']) ? $this->stdWrap(
45
            $conf['parameter'],
46
            $conf['parameter.']
47
        ) : $conf['parameter']);
48
        $this->lastTypoLinkUrl = '';
49
        $this->lastTypoLinkTarget = '';
50
51
        $resolvedLinkParameters = $this->resolveMixedLinkParameter($linktxt, $linkParameter, $conf);
52
        // check if the link handler hook has resolved the link completely already
53
        if (!is_array($resolvedLinkParameters)) {
54
            return $resolvedLinkParameters;
55
        }
56
57
        $linkParameter = $resolvedLinkParameters['href'];
58
        $forceTarget = $resolvedLinkParameters['target'];
59
        $linkClass = $resolvedLinkParameters['class'];
60
        $forceTitle = $resolvedLinkParameters['title'];
61
62
        if (!$linkParameter) {
63
            return $linktxt;
64
        }
65
66
        // Check, if the target is coded as a JS open window link:
67
        $JSwindowParts = array();
68
        $JSwindowParams = '';
69
        if ($forceTarget && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/', $forceTarget, $JSwindowParts)) {
70
            // Take all pre-configured and inserted parameters and compile parameter list, including width+height:
71
            $JSwindow_tempParamsArr = GeneralUtility::trimExplode(
72
                ',',
73
                strtolower($conf['JSwindow_params'] . ',' . $JSwindowParts[4]),
74
                true
75
            );
76
            $JSwindow_paramsArr = array();
77
            foreach ($JSwindow_tempParamsArr as $JSv) {
78
                list($JSp, $JSv) = explode('=', $JSv, 2);
79
                $JSwindow_paramsArr[$JSp] = $JSp . '=' . $JSv;
80
            }
81
            // Add width/height:
82
            $JSwindow_paramsArr['width'] = 'width=' . $JSwindowParts[1];
83
            $JSwindow_paramsArr['height'] = 'height=' . $JSwindowParts[2];
84
            // Imploding into string:
85
            $JSwindowParams = implode(',', $JSwindow_paramsArr);
86
            // Resetting the target since we will use onClick.
87
            $forceTarget = '';
88
        }
89
90
        // Internal target:
91
        if ($tsfe->dtdAllowsFrames) {
92
            $target = isset($conf['target']) ? $conf['target'] : $tsfe->intTarget;
93
        } else {
94
            $target = isset($conf['target']) ? $conf['target'] : '';
95
        }
96
        if ($conf['target.']) {
97
            $target = $this->stdWrap($target, $conf['target.']);
98
        }
99
100
        // Title tag
101
        $title = $conf['title'];
102
        if ($conf['title.']) {
103
            $title = $this->stdWrap($title, $conf['title.']);
104
        }
105
106
        $theTypeP = 0;
107
        // Detecting kind of link
108
        $linkType = $this->detectLinkTypeFromLinkParameter($linkParameter);
109
        switch ($linkType) {
110
            // If it's a mail address
111
            case 'mailto':
112
                $linkParameter = preg_replace('/^mailto:/i', '', $linkParameter);
113
                list($this->lastTypoLinkUrl, $linktxt) = $this->getMailTo($linkParameter, $linktxt);
114
                $finalTagParts['url'] = $this->lastTypoLinkUrl;
115
                break;
116
117
            // url (external): If doubleSlash or if a '.' comes before a '/'.
118
            case 'url':
119
                if ($tsfe->dtdAllowsFrames) {
120
                    $target = isset($conf['extTarget']) ? $conf['extTarget'] : $tsfe->extTarget;
121
                } else {
122
                    $target = isset($conf['extTarget']) ? $conf['extTarget'] : '';
123
                }
124
                if ($conf['extTarget.']) {
125
                    $target = $this->stdWrap($target, $conf['extTarget.']);
126
                }
127
                if ($forceTarget) {
128
                    $target = $forceTarget;
129
                }
130
                if ($linktxt === '') {
131
                    $linktxt = $this->parseFunc($linkParameter, array('makelinks' => 0), '< lib.parseFunc');
132
                }
133
                // Parse URL:
134
                $urlParts = parse_url($linkParameter);
135
                if (!$urlParts['scheme']) {
136
                    $scheme = 'http://';
137
                } else {
138
                    $scheme = '';
139
                }
140
141
                $this->lastTypoLinkUrl = $this->processUrl(
142
                    UrlProcessorInterface::CONTEXT_EXTERNAL,
143
                    $scheme . $linkParameter,
144
                    $conf
145
                );
146
147
                $this->lastTypoLinkTarget = $target;
148
                $finalTagParts['url'] = $this->lastTypoLinkUrl;
149
                $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
150
                $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $linkType);
151
                break;
152
153
            // file (internal)
154
            case 'file':
155
                $splitLinkParam = explode('?', $linkParameter);
156
157
                // check if the file exists or if a / is contained (same check as in detectLinkType)
158
                if (file_exists(rawurldecode($splitLinkParam[0])) || strpos($linkParameter, '/') !== false) {
159
                    if ($linktxt === '') {
160
                        $linktxt = $this->parseFunc(rawurldecode($linkParameter), array('makelinks' => 0), '< lib.parseFunc');
161
                    }
162
                    $this->lastTypoLinkUrl = $this->processUrl(
163
                        UrlProcessorInterface::CONTEXT_FILE,
164
                        $GLOBALS['TSFE']->absRefPrefix . $linkParameter,
165
                        $conf
166
                    );
167
                    $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
168
                    $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $tsfe->fileTarget;
169
                    if ($conf['fileTarget.']) {
170
                        $target = $this->stdWrap($target, $conf['fileTarget.']);
171
                    }
172
                    if ($forceTarget) {
173
                        $target = $forceTarget;
174
                    }
175
                    $this->lastTypoLinkTarget = $target;
176
                    $finalTagParts['url'] = $this->lastTypoLinkUrl;
177
                    $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
178
                    $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $linkType);
179
                } else {
180
                    $this->getTimeTracker()
181
                        ->setTSlogMessage(
182
                            'typolink(): File "' . $splitLinkParam[0] . '" did not exist, so "' . $linktxt . '" was not linked.',
183
                            1
184
                        );
185
                    return $linktxt;
186
                }
187
                break;
188
189
            // Integer or alias (alias is without slashes or periods or commas, that is
190
            // 'nospace,alphanum_x,lower,unique' according to definition in $GLOBALS['TCA']!)
191
            case 'page':
192
                $enableLinksAcrossDomains = $tsfe->config['config']['typolinkEnableLinksAcrossDomains'];
193
194
                if ($conf['no_cache.']) {
195
                    $conf['no_cache'] = $this->stdWrap($conf['no_cache'], $conf['no_cache.']);
196
                }
197
                // Splitting the parameter by ',' and if the array counts more than 1 element it's an id/type/parameters triplet
198
                $pairParts = GeneralUtility::trimExplode(',', $linkParameter, true);
199
                $linkParameter = $pairParts[0];
200
                $link_params_parts = explode('#', $linkParameter);
201
                // Link-data del
202
                $linkParameter = trim($link_params_parts[0]);
203
                // If no id or alias is given
204
                if ($linkParameter === '') {
205
                    $linkParameter = $tsfe->id;
206
                }
207
208
                $sectionMark = trim(isset($conf['section.']) ? $this->stdWrap(
209
                    $conf['section'],
210
                    $conf['section.']
211
                ) : $conf['section']);
212
                if ($sectionMark !== '') {
213
                    $sectionMark = '#' . (MathUtility::canBeInterpretedAsInteger($sectionMark) ? 'c' : '') . $sectionMark;
214
                }
215
216
                if ($link_params_parts[1] && $sectionMark === '') {
217
                    $sectionMark = trim($link_params_parts[1]);
218
                    $sectionMark = '#' . (MathUtility::canBeInterpretedAsInteger($sectionMark) ? 'c' : '') . $sectionMark;
219
                }
220
                if (count($pairParts) > 1) {
221
                    // Overruling 'type'
222
                    $theTypeP = isset($pairParts[1]) ? $pairParts[1] : 0;
223
                    $conf['additionalParams'] .= isset($pairParts[2]) ? $pairParts[2] : '';
224
                }
225
                // Checking if the id-parameter is an alias.
226
                if (!MathUtility::canBeInterpretedAsInteger($linkParameter)) {
227
                    $linkParameter = $tsfe->sys_page->getPageIdFromAlias($linkParameter);
228
                }
229
                // Link to page even if access is missing?
230
                if (isset($conf['linkAccessRestrictedPages'])) {
231
                    $disableGroupAccessCheck = (bool)$conf['linkAccessRestrictedPages'];
232
                } else {
233
                    $disableGroupAccessCheck = (bool)$tsfe->config['config']['typolinkLinkAccessRestrictedPages'];
234
                }
235
                // Looking up the page record to verify its existence:
236
                $page = $tsfe->sys_page->getPage($linkParameter, $disableGroupAccessCheck);
237
                if (!empty($page)) {
238
                    // MointPoints, look for closest MPvar:
239
                    $MPvarAcc = array();
240
                    if (!$tsfe->config['config']['MP_disableTypolinkClosestMPvalue']) {
241
                        $temp_MP = $this->getClosestMPvalueForPage($page['uid'], true);
242
                        if ($temp_MP) {
243
                            $MPvarAcc['closest'] = $temp_MP;
244
                        }
245
                    }
246
                    // Look for overlay Mount Point:
247
                    $mount_info = $tsfe->sys_page->getMountPointInfo($page['uid'], $page);
248
                    if (is_array($mount_info) && $mount_info['overlay']) {
249
                        $page = $tsfe->sys_page->getPage($mount_info['mount_pid'], $disableGroupAccessCheck);
250
                        if (empty($page)) {
251
                            $this->getTimeTracker()
252
                                ->setTSlogMessage(
253
                                    'typolink(): Mount point "' . $mount_info['mount_pid'] . '" was not available, so "' . $linktxt . '" was not linked.',
254
                                    1
255
                                );
256
                            return $linktxt;
257
                        }
258
                        $MPvarAcc['re-map'] = $mount_info['MPvar'];
259
                    }
260
261
262
                    // -----------------------
263
                    // Popup Hook
264
                    // -----------------------
265
                    $pageRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
266
                    $popup = $pageRepository->checkRecord('pages', $page['uid']);
267
                    $popup_configuration = $popup['tx_popup_configuration'];
268
269
270
                    // Setting title if blank value to link:
271
                    if ($linktxt === '') {
272
                        $linktxt = $this->parseFunc($page['title'], array('makelinks' => 0), '< lib.parseFunc');
273
                    }
274
                    // Query Params:
275
                    $addQueryParams = $conf['addQueryString'] ? $this->getQueryArguments($conf['addQueryString.']) : '';
276
                    $addQueryParams .= isset($conf['additionalParams.']) ? trim($this->stdWrap(
277
                        $conf['additionalParams'],
278
                        $conf['additionalParams.']
279
                    )) : trim($conf['additionalParams']);
280
                    if ($addQueryParams === '&' || $addQueryParams[0] !== '&') {
281
                        $addQueryParams = '';
282
                    }
283
                    if ($conf['useCacheHash']) {
284
                        // Mind the order below! See http://forge.typo3.org/issues/17070
285
                        $params = $tsfe->linkVars . $addQueryParams;
286
                        if (trim($params, '& ') != '') {
287
                            /** @var $cacheHash CacheHashCalculator */
288
                            $cacheHash = GeneralUtility::makeInstance(CacheHashCalculator::class);
289
                            $cHash = $cacheHash->generateForParameters($params);
290
                            $addQueryParams .= $cHash ? '&cHash=' . $cHash : '';
291
                        }
292
                        unset($params);
293
                    }
294
                    $targetDomain = '';
295
                    $currentDomain = (string)$this->getEnvironmentVariable('HTTP_HOST');
296
                    // Mount pages are always local and never link to another domain
297
                    if (!empty($MPvarAcc)) {
298
                        // Add "&MP" var:
299
                        $addQueryParams .= '&MP=' . rawurlencode(implode(',', $MPvarAcc));
300
                    } elseif (strpos($addQueryParams, '&MP=') === false && $tsfe->config['config']['typolinkCheckRootline']) {
301
                        // We do not come here if additionalParams had '&MP='. This happens when typoLink is called from
302
                        // menu. Mount points always work in the content of the current domain and we must not change
303
                        // domain if MP variables exist.
304
                        // If we link across domains and page is free type shortcut, we must resolve the shortcut first!
305
                        // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because
306
                        // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked
307
                        if ($enableLinksAcrossDomains && (int)$page['doktype'] === PageRepository::DOKTYPE_SHORTCUT && (int)$page['shortcut_mode'] === PageRepository::SHORTCUT_MODE_NONE) {
308
                            // Save in case of broken destination or endless loop
309
                            $page2 = $page;
310
                            // Same as in RealURL, seems enough
311
                            $maxLoopCount = 20;
312
                            while ($maxLoopCount && is_array($page) && (int)$page['doktype'] === PageRepository::DOKTYPE_SHORTCUT && (int)$page['shortcut_mode'] === PageRepository::SHORTCUT_MODE_NONE) {
313
                                $page = $tsfe->sys_page->getPage($page['shortcut'], $disableGroupAccessCheck);
314
                                $maxLoopCount--;
315
                            }
316
                            if (empty($page) || $maxLoopCount === 0) {
317
                                // We revert if shortcut is broken or maximum number of loops is exceeded (indicates endless loop)
318
                                $page = $page2;
319
                            }
320
                        }
321
322
                        $targetDomain = $tsfe->getDomainNameForPid($page['uid']);
323
                        // Do not prepend the domain if it is the current hostname
324
                        if (!$targetDomain || $tsfe->domainNameMatchesCurrentRequest($targetDomain)) {
325
                            $targetDomain = '';
326
                        }
327
                    }
328
                    $absoluteUrlScheme = 'http';
329
                    // URL shall be absolute:
330
                    if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl'] || $page['url_scheme'] > 0) {
331
                        // Override scheme:
332
                        if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) {
333
                            $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme'];
334
                        } elseif ($page['url_scheme'] > 0) {
335
                            $absoluteUrlScheme = (int)$page['url_scheme'] === HttpUtility::SCHEME_HTTP ? 'http' : 'https';
336
                        } elseif ($this->getEnvironmentVariable('TYPO3_SSL')) {
337
                            $absoluteUrlScheme = 'https';
338
                        }
339
                        // If no domain records are defined, use current domain:
340
                        $currentUrlScheme = parse_url($this->getEnvironmentVariable('TYPO3_REQUEST_URL'), PHP_URL_SCHEME);
341
                        if ($targetDomain === '' && ($conf['forceAbsoluteUrl'] || $absoluteUrlScheme !== $currentUrlScheme)) {
342
                            $targetDomain = $currentDomain;
343
                        }
344
                        // If go for an absolute link, add site path if it's not taken care about by absRefPrefix
345
                        if (!$tsfe->config['config']['absRefPrefix'] && $targetDomain === $currentDomain) {
346
                            $targetDomain = $currentDomain . rtrim($this->getEnvironmentVariable('TYPO3_SITE_PATH'), '/');
347
                        }
348
                    }
349
                    // If target page has a different domain and the current domain's linking scheme (e.g. RealURL/...) should not be used
350
                    if ($targetDomain !== '' && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) {
351
                        $target = isset($conf['extTarget']) ? $conf['extTarget'] : $tsfe->extTarget;
352
                        if ($conf['extTarget.']) {
353
                            $target = $this->stdWrap($target, $conf['extTarget.']);
354
                        }
355
                        if ($forceTarget) {
356
                            $target = $forceTarget;
357
                        }
358
                        $LD['target'] = $target;
359
                        // Convert IDNA-like domain (if any)
360
                        if (!preg_match('/^[a-z0-9.\\-]*$/i', $targetDomain)) {
361
                            $targetDomain = GeneralUtility::idnaEncode($targetDomain);
362
                        }
363
                        $this->lastTypoLinkUrl = $this->URLqMark(
364
                            $absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'],
365
                            $addQueryParams
366
                        ) . $sectionMark;
367
                    } else {
368
                        // Internal link or current domain's linking scheme should be used
369
                        if ($forceTarget) {
370
                            $target = $forceTarget;
371
                        }
372
                        $LD = $tsfe->tmpl->linkData(
373
                            $page,
374
                            $target,
375
                            $conf['no_cache'],
376
                            '',
377
                            '',
0 ignored issues
show
'' is of type string, but the function expects a array|null.

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...
378
                            $addQueryParams,
379
                            $theTypeP,
380
                            $targetDomain
381
                        );
382
                        if ($targetDomain !== '') {
383
                            // We will add domain only if URL does not have it already.
384
                            if ($enableLinksAcrossDomains && $targetDomain !== $currentDomain) {
385
                                // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only
386
                                // to the current web site. If we have domain here it means we link across
387
                                // domains. absRefPrefix can contain domain name, which will screw up
388
                                // the link to the external domain.
389
                                $prefixLength = strlen($tsfe->config['config']['absRefPrefix']);
390
                                if (substr($LD['totalURL'], 0, $prefixLength) === $tsfe->config['config']['absRefPrefix']) {
391
                                    $LD['totalURL'] = substr($LD['totalURL'], $prefixLength);
392
                                }
393
                            }
394
                            $urlParts = parse_url($LD['totalURL']);
395
                            if (empty($urlParts['host'])) {
396
                                $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain . ($LD['totalURL'][0] === '/' ? '' : '/') . $LD['totalURL'];
397
                            }
398
                        }
399
                        $this->lastTypoLinkUrl = $this->URLqMark($LD['totalURL'], '') . $sectionMark;
400
                    }
401
                    $this->lastTypoLinkTarget = $LD['target'];
402
                    // If sectionMark is set, there is no baseURL AND the current page is the page the link is to, check if there are any additional parameters or addQueryString parameters and if not, drop the url.
403
                    if ($sectionMark && !$tsfe->config['config']['baseURL'] && (int)$page['uid'] === (int)$tsfe->id && !trim($addQueryParams) && (empty($conf['addQueryString']) || !isset($conf['addQueryString.']))) {
404
                        $currentQueryParams = $this->getQueryArguments(array());
405
                        if (!trim($currentQueryParams)) {
406
                            list(, $URLparams) = explode('?', $this->lastTypoLinkUrl);
407
                            list($URLparams) = explode('#', $URLparams);
408
                            parse_str($URLparams . $LD['orig_type'], $URLparamsArray);
409
                            // Type nums must match as well as page ids
410
                            if ((int)$URLparamsArray['type'] === (int)$tsfe->type) {
411
                                unset($URLparamsArray['id']);
412
                                unset($URLparamsArray['type']);
413
                                // If there are no parameters left.... set the new url.
414
                                if (empty($URLparamsArray)) {
415
                                    $this->lastTypoLinkUrl = $sectionMark;
416
                                }
417
                            }
418
                        }
419
                    }
420
                    // If link is to an access restricted page which should be redirected, then find new URL:
421
                    if (empty($conf['linkAccessRestrictedPages']) && $tsfe->config['config']['typolinkLinkAccessRestrictedPages'] && $tsfe->config['config']['typolinkLinkAccessRestrictedPages'] !== 'NONE' && !$tsfe->checkPageGroupAccess($page)) {
422
                        $thePage = $tsfe->sys_page->getPage($tsfe->config['config']['typolinkLinkAccessRestrictedPages']);
423
                        $addParams = str_replace(array(
424
                            '###RETURN_URL###',
425
                            '###PAGE_ID###'
426
                        ), array(
427
                            rawurlencode($this->lastTypoLinkUrl),
428
                            $page['uid']
429
                        ), $tsfe->config['config']['typolinkLinkAccessRestrictedPages_addParams']);
430
                        $this->lastTypoLinkUrl = $this->getTypoLink_URL(
431
                            $thePage['uid'] . ($theTypeP ? ',' . $theTypeP : ''),
432
                            $addParams,
433
                            $target
434
                        );
435
                        $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
436
                        $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
437
                        $LD = $this->lastTypoLinkLD;
438
                    }
439
                    // Rendering the tag.
440
                    $finalTagParts['url'] = $this->lastTypoLinkUrl;
441
                    $finalTagParts['targetParams'] = (string)$LD['target'] !== '' ? ' target="' . htmlspecialchars($LD['target']) . '"' : '';
442
                } else {
443
                    $this->getTimeTracker()
444
                        ->setTSlogMessage(
445
                            'typolink(): Page id "' . $linkParameter . '" was not found, so "' . $linktxt . '" was not linked.',
446
                            1
447
                        );
448
                    return $linktxt;
449
                }
450
                break;
451
        }
452
453
        $finalTagParts['TYPE'] = $linkType;
454
        $this->lastTypoLinkLD = $LD;
455
456
        if ($forceTitle) {
457
            $title = $forceTitle;
458
        }
459
460
        if ($JSwindowParams) {
461
            // Create TARGET-attribute only if the right doctype is used
462
            $xhtmlDocType = $tsfe->xhtmlDoctype;
463
            if ($xhtmlDocType !== 'xhtml_strict' && $xhtmlDocType !== 'xhtml_11' && $xhtmlDocType !== 'xhtml_2') {
464
                $target = ' target="FEopenLink"';
465
            } else {
466
                $target = '';
467
            }
468
            $onClick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($tsfe->baseUrlWrap($finalTagParts['url'])) . ',\'FEopenLink\',' . GeneralUtility::quoteJSvalue($JSwindowParams) . ');vHWin.focus();return false;';
469
            $finalAnchorTag = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' . $target . ' onclick="' . htmlspecialchars($onClick) . '"' . ((string)$title !== '' ? ' title="' . htmlspecialchars($title) . '"' : '') . ($linkClass !== '' ? ' class="' . $linkClass . '"' : '') . $finalTagParts['aTagParams'] . '>';
470
        } else {
471
            if ($tsfe->spamProtectEmailAddresses === 'ascii' && $linkType === 'mailto') {
472
                $finalAnchorTag = '<a href="' . $finalTagParts['url'] . '"';
473
            } else {
474
                $finalAnchorTag = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"';
475
476
477
                // -----------------------
478
                // Popup Hook
479
                // -----------------------
480
                if (isset($popup_configuration) && strlen($popup_configuration)) {
481
                    $popup = GeneralUtility::makeInstance('FRUIT\\Popup\\Popup');
482
                    $popup_configuration = $popup->convertCfg2Js($popup_configuration);
483
                    $finalTagParts['aTagParams'] .= ' onclick="window.open(this.href,\'\',\'' . $popup_configuration . '\'); return false;"';
484
                }
485
            }
486
            $finalAnchorTag .= ((string)$title !== '' ? ' title="' . htmlspecialchars($title) . '"' : '') . $finalTagParts['targetParams'] . ($linkClass ? ' class="' . $linkClass . '"' : '') . $finalTagParts['aTagParams'] . '>';
487
        }
488
489
        // Call user function:
490
        if ($conf['userFunc']) {
491
            $finalTagParts['TAG'] = $finalAnchorTag;
492
            $finalAnchorTag = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $finalTagParts);
493
        }
494
495
        // Hook: Call post processing function for link rendering:
496
        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])) {
497
            $_params = array(
498
                'conf'          => &$conf,
499
                'linktxt'       => &$linktxt,
500
                'finalTag'      => &$finalAnchorTag,
501
                'finalTagParts' => &$finalTagParts
502
            );
503
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] as $_funcRef) {
504
                GeneralUtility::callUserFunction($_funcRef, $_params, $this);
505
            }
506
        }
507
508
        // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
509
        if ($conf['returnLast']) {
510
            switch ($conf['returnLast']) {
511
                case 'url':
512
                    return $this->lastTypoLinkUrl;
513
                    break;
514
                case 'target':
515
                    return $this->lastTypoLinkTarget;
516
                    break;
517
            }
518
        }
519
520
        $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
521
522
        if ($conf['ATagBeforeWrap']) {
523
            return $finalAnchorTag . $this->wrap($linktxt, $wrap) . '</a>';
524
        }
525
        return $this->wrap($finalAnchorTag . $linktxt . '</a>', $wrap);
526
    }
527
}
528