function FieldPluginBase::renderAsLink

Same name in other branches
  1. 9 core/modules/views/src/Plugin/views/field/FieldPluginBase.php \Drupal\views\Plugin\views\field\FieldPluginBase::renderAsLink()
  2. 8.9.x core/modules/views/src/Plugin/views/field/FieldPluginBase.php \Drupal\views\Plugin\views\field\FieldPluginBase::renderAsLink()
  3. 11.x core/modules/views/src/Plugin/views/field/FieldPluginBase.php \Drupal\views\Plugin\views\field\FieldPluginBase::renderAsLink()

Render this field as a link, with the info from a fieldset set by the user.

1 call to FieldPluginBase::renderAsLink()
FieldPluginBase::renderText in core/modules/views/src/Plugin/views/field/FieldPluginBase.php
Performs an advanced text render for the item.

File

core/modules/views/src/Plugin/views/field/FieldPluginBase.php, line 1432

Class

FieldPluginBase
Base class for views fields.

Namespace

Drupal\views\Plugin\views\field

Code

protected function renderAsLink($alter, $text, $tokens) {
    $options = [
        'absolute' => !empty($alter['absolute']) ? TRUE : FALSE,
        'alias' => FALSE,
        'entity' => NULL,
        'entity_type' => NULL,
        'fragment' => NULL,
        'language' => NULL,
        'query' => [],
    ];
    $alter += [
        'path' => NULL,
    ];
    $path = $alter['path'];
    // strip_tags() and viewsTokenReplace remove <front>, so check whether it's
    // different to front.
    if ($path != '<front>') {
        // Use strip_tags as there should never be HTML in the path.
        // However, we need to preserve special characters like " that were
        // removed by Html::escape().
        $path = Html::decodeEntities($this->viewsTokenReplace($alter['path'], $tokens));
        // Tokens might contain <front>, so check for <front> again.
        if ($path != '<front>') {
            $path = strip_tags($path);
        }
        // Tokens might have resolved URL's, as is the case for tokens provided by
        // Link fields, so all internal paths will be prefixed by base_path(). For
        // proper further handling reset this to internal:/.
        if (str_starts_with($path, base_path())) {
            $path = 'internal:/' . substr($path, strlen(base_path()));
        }
        // If we have no $path and no $alter['url'], we have nothing to work with,
        // so we just return the text.
        if (empty($path) && empty($alter['url'])) {
            return $text;
        }
        // If no scheme is provided in the $path, assign the default 'http://'.
        // This allows a URL of 'www.example.com' to be converted to
        // 'http://www.example.com'.
        // Only do this when flag for external has been set, $path doesn't contain
        // a scheme and $path doesn't have a leading /.
        if ($alter['external'] && !parse_url($path, PHP_URL_SCHEME) && !str_starts_with($path, '/')) {
            // There is no scheme, add the default 'http://' to the $path.
            $path = "http://" . $path;
        }
    }
    if (empty($alter['url'])) {
        if (!parse_url($path, PHP_URL_SCHEME)) {
            // @todo Views should expect and store a leading /. See
            //   https://www.drupal.org/node/2423913.
            $alter['url'] = CoreUrl::fromUserInput('/' . ltrim($path, '/'));
        }
        else {
            $alter['url'] = CoreUrl::fromUri($path);
        }
    }
    $options = $alter['url']->getOptions() + $options;
    $path = $alter['url']->setOptions($options)
        ->toUriString();
    if (!empty($alter['path_case']) && $alter['path_case'] != 'none' && !$alter['url']->isRouted()) {
        $path = str_replace($alter['path'], $this->caseTransform($alter['path'], $this->options['alter']['path_case']), $path);
    }
    if (!empty($alter['replace_spaces'])) {
        $path = str_replace(' ', '-', $path);
    }
    // Parse the URL and move any query and fragment parameters out of the path.
    $url = UrlHelper::parse($path);
    // Seriously malformed URLs may return FALSE or empty arrays.
    if (empty($url)) {
        return $text;
    }
    // If the path is empty do not build a link around the given text and return
    // it as is.
    // http://www.example.com URLs will not have a $url['path'], so check host as well.
    if (empty($url['path']) && empty($url['host']) && empty($url['fragment']) && empty($url['url'])) {
        return $text;
    }
    // If we get to here we have a path from the URL parsing. So assign that to
    // $path now so we don't get query strings or fragments in the path.
    $path = $url['path'];
    if (isset($url['query'])) {
        // Remove query parameters that were assigned a query string replacement
        // token for which there is no value available.
        foreach ($url['query'] as $param => $val) {
            if ($val == '%' . $param) {
                unset($url['query'][$param]);
            }
            // Replace any empty query params from URL parsing with NULL. So the
            // query will get built correctly with only the param key.
            // @see \Drupal\Component\Utility\UrlHelper::buildQuery().
            if ($val === '') {
                $url['query'][$param] = NULL;
            }
        }
        $options['query'] = $url['query'];
    }
    if (isset($url['fragment'])) {
        $path = strtr($path, [
            '#' . $url['fragment'] => '',
        ]);
        // If the path is empty we want to have a fragment for the current site.
        if ($path == '') {
            $options['external'] = TRUE;
        }
        $options['fragment'] = $url['fragment'];
    }
    $alt = $this->viewsTokenReplace($alter['alt'], $tokens);
    // Set the title attribute of the link only if it improves accessibility
    if ($alt && $alt != $text) {
        $options['attributes']['title'] = Html::decodeEntities($alt);
    }
    $class = $this->viewsTokenReplace($alter['link_class'], $tokens);
    if ($class) {
        $options['attributes']['class'] = [
            $class,
        ];
    }
    if (!empty($alter['rel']) && ($rel = $this->viewsTokenReplace($alter['rel'], $tokens))) {
        $options['attributes']['rel'] = $rel;
    }
    $target = trim($this->viewsTokenReplace($alter['target'], $tokens));
    if (!empty($target)) {
        $options['attributes']['target'] = $target;
    }
    // Allow the addition of arbitrary attributes to links. Additional attributes
    // currently can only be altered in preprocessors and not within the UI.
    if (isset($alter['link_attributes']) && is_array($alter['link_attributes'])) {
        foreach ($alter['link_attributes'] as $key => $attribute) {
            if (!isset($options['attributes'][$key])) {
                $options['attributes'][$key] = $this->viewsTokenReplace($attribute, $tokens);
            }
        }
    }
    // If the query and fragment were programmatically assigned overwrite any
    // parsed values.
    if (isset($alter['query'])) {
        // Convert the query to a string, perform token replacement, and then
        // convert back to an array form for
        // \Drupal\Core\Utility\LinkGeneratorInterface::generate().
        $options['query'] = UrlHelper::buildQuery($alter['query']);
        $options['query'] = $this->viewsTokenReplace($options['query'], $tokens);
        $query = [];
        parse_str($options['query'], $query);
        $options['query'] = $query;
    }
    if (isset($alter['alias'])) {
        // Alias is a boolean field, so no token.
        $options['alias'] = $alter['alias'];
    }
    if (isset($alter['fragment'])) {
        $options['fragment'] = $this->viewsTokenReplace($alter['fragment'], $tokens);
    }
    if (isset($alter['language'])) {
        $options['language'] = $alter['language'];
    }
    // If the URL came from entity_uri(), pass along the required options.
    if (isset($alter['entity'])) {
        $options['entity'] = $alter['entity'];
    }
    if (isset($alter['entity_type'])) {
        $options['entity_type'] = $alter['entity_type'];
    }
    // The path has been heavily processed above, so it should be used as-is.
    $final_url = CoreUrl::fromUri($path, $options);
    // Build the link based on our altered Url object, adding on the optional
    // prefix and suffix
    $render = [
        '#type' => 'link',
        '#title' => $text,
        '#url' => $final_url,
    ];
    if (!empty($alter['prefix'])) {
        $render['#prefix'] = $this->viewsTokenReplace($alter['prefix'], $tokens);
    }
    if (!empty($alter['suffix'])) {
        $render['#suffix'] = $this->viewsTokenReplace($alter['suffix'], $tokens);
    }
    return $this->getRenderer()
        ->render($render);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.