예제 #1
1
 /**
  * {@inheritdoc}
  */
 public function validate($value, Constraint $constraint)
 {
     if (isset($value)) {
         $url_is_valid = TRUE;
         /** @var $link_item \Drupal\link\LinkItemInterface */
         $link_item = $value;
         $link_type = $link_item->getFieldDefinition()->getSetting('link_type');
         $url_string = $link_item->url;
         // Validate the url property.
         if ($url_string !== '') {
             try {
                 // @todo This shouldn't be needed, but massageFormValues() may not
                 //   run.
                 $parsed_url = UrlHelper::parse($url_string);
                 $url = Url::createFromPath($parsed_url['path']);
                 if ($url->isExternal() && !UrlHelper::isValid($url_string, TRUE)) {
                     $url_is_valid = FALSE;
                 } elseif ($url->isExternal() && !($link_type & LinkItemInterface::LINK_EXTERNAL)) {
                     $url_is_valid = FALSE;
                 }
             } catch (NotFoundHttpException $e) {
                 $url_is_valid = FALSE;
             } catch (MatchingRouteNotFoundException $e) {
                 $url_is_valid = FALSE;
             } catch (ParamNotConvertedException $e) {
                 $url_is_valid = FALSE;
             }
         }
         if (!$url_is_valid) {
             $this->context->addViolation($this->message, array('%url' => $url_string));
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function getUrlIfValid($path)
 {
     $parsed_url = UrlHelper::parse($path);
     $options = [];
     if (!empty($parsed_url['query'])) {
         $options['query'] = $parsed_url['query'];
     }
     if (!empty($parsed_url['fragment'])) {
         $options['fragment'] = $parsed_url['fragment'];
     }
     if ($parsed_url['path'] == '<front>') {
         return new Url('<front>', [], $options);
     } elseif (UrlHelper::isExternal($path) && UrlHelper::isValid($path)) {
         if (empty($parsed_url['path'])) {
             return FALSE;
         }
         return Url::fromUri($path);
     }
     $path = ltrim($path, '/');
     $request = Request::create('/' . $path);
     $attributes = $this->getPathAttributes($path, $request);
     if (!$attributes) {
         return FALSE;
     }
     $route_name = $attributes[RouteObjectInterface::ROUTE_NAME];
     $route_parameters = $attributes['_raw_variables']->all();
     return new Url($route_name, $route_parameters, $options + ['query' => $request->query->all()]);
 }
예제 #3
0
 /**
  * {@inheritdoc}
  */
 public function execute($object = NULL)
 {
     $url = $this->configuration['url'];
     // Leave external URLs unchanged, and assemble others as absolute URLs
     // relative to the site's base URL.
     if (!UrlHelper::isExternal($url)) {
         $parts = UrlHelper::parse($url);
         // @todo '<front>' is valid input for BC reasons, may be removed by
         //   https://www.drupal.org/node/2421941
         if ($parts['path'] === '<front>') {
             $parts['path'] = '';
         }
         $uri = 'base:' . $parts['path'];
         $options = ['query' => $parts['query'], 'fragment' => $parts['fragment'], 'absolute' => TRUE];
         // Treat this as if it's user input of a path relative to the site's
         // base URL.
         $url = $this->unroutedUrlAssembler->assemble($uri, $options);
     }
     $response = new RedirectResponse($url);
     $listener = function ($event) use($response) {
         $event->setResponse($response);
     };
     // Add the listener to the event dispatcher.
     $this->dispatcher->addListener(KernelEvents::RESPONSE, $listener);
 }
  /**
   * @param $url
   *
   * @see FillPdfLinkManipulatorInterface::parseUrlString()
   *
   * @return \Drupal\Core\Url
   */
  protected function createUrlFromString($url) {
    $url_parts = UrlHelper::parse($url);
    $path = $url_parts['path'];
    $query = $url_parts['query'];

    $link = Url::fromUri($path, ['query' => $query]);
    return $link;
  }
예제 #5
0
 /**
  * {@inheritdoc}
  */
 public function setEmbedProvider($provider)
 {
     $provider_parsed = UrlHelper::parse($provider);
     $provider_parsed['query'] = array_filter($provider_parsed['query'], function ($value) {
         return $value !== '{callback}';
     });
     $provider_parsed['absolute'] = TRUE;
     $this->embed_provider = $this->urlAssembler->assemble($provider_parsed['path'], $provider_parsed);
 }
예제 #6
0
 /**
  * Returns the next redirect path in a multipage sequence.
  *
  * @param array $destinations
  *   An array of destinations to redirect to.
  *
  * @return array
  *   The next destination to redirect to.
  */
 public static function getNextDestination(array $destinations)
 {
     $next_destination = array_shift($destinations);
     if (is_array($next_destination)) {
         $next_destination['options']['query']['destinations'] = $destinations;
     } else {
         $options = UrlHelper::parse($next_destination);
         if ($destinations) {
             $options['query']['destinations'] = $destinations;
         }
         $next_destination = array($options['path'], $options);
     }
     return $next_destination;
 }
예제 #7
0
 /**
  * Builds the cancel link for a confirmation form.
  *
  * @param \Drupal\Core\Form\ConfirmFormInterface $form
  *   The confirmation form.
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request.
  *
  * @return array
  *   The link render array for the cancel form.
  */
 public static function buildCancelLink(ConfirmFormInterface $form, Request $request)
 {
     // Prepare cancel link.
     $query = $request->query;
     // If a destination is specified, that serves as the cancel link.
     if ($query->has('destination')) {
         $options = UrlHelper::parse($query->get('destination'));
         // @todo Revisit this in https://www.drupal.org/node/2418219.
         $url = Url::fromUserInput('/' . $options['path'], $options);
     } else {
         $url = $form->getCancelUrl();
     }
     return ['#type' => 'link', '#title' => $form->getCancelText(), '#attributes' => ['class' => ['button']], '#url' => $url];
 }
 /**
  * Builds the cancel link for a confirmation form.
  *
  * @param \Drupal\Core\Form\ConfirmFormInterface $form
  *   The confirmation form.
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request.
  *
  * @return array
  *   The link render array for the cancel form.
  */
 public static function buildCancelLink(ConfirmFormInterface $form, Request $request)
 {
     // Prepare cancel link.
     $query = $request->query;
     // If a destination is specified, that serves as the cancel link.
     if ($query->has('destination')) {
         $options = UrlHelper::parse($query->get('destination'));
         // @todo Use Url::fromPath() once https://www.drupal.org/node/2351379 is
         //   resolved.
         $url = Url::fromUri('base://' . $options['path'], $options);
     } else {
         $url = $form->getCancelUrl();
     }
     return ['#type' => 'link', '#title' => $form->getCancelText(), '#url' => $url];
 }
예제 #9
0
 /**
  * Builds the cancel link for a confirmation form.
  *
  * @param \Drupal\Core\Form\ConfirmFormInterface $form
  *   The confirmation form.
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request.
  *
  * @return array
  *   The link render array for the cancel form.
  */
 public static function buildCancelLink(ConfirmFormInterface $form, Request $request)
 {
     // Prepare cancel link.
     $query = $request->query;
     // If a destination is specified, that serves as the cancel link.
     if ($query->has('destination')) {
         $options = UrlHelper::parse($query->get('destination'));
         $link = array('#href' => $options['path'], '#options' => $options);
     } elseif ($route = $form->getCancelRoute()) {
         $link = $route->toRenderArray();
     }
     $link['#type'] = 'link';
     $link['#title'] = $form->getCancelText();
     return $link;
 }
예제 #10
0
 /**
  * Returns the next redirect path in a multipage sequence.
  *
  * @param array $destinations
  *   An array of destinations to redirect to.
  *
  * @return \Drupal\Core\Url
  *   The next destination to redirect to.
  */
 public static function getNextDestination(array $destinations)
 {
     $next_destination = array_shift($destinations);
     if (is_array($next_destination)) {
         $next_destination['options']['query']['destinations'] = $destinations;
         $next_destination += array('route_parameters' => array());
         $next_destination = Url::fromRoute($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']);
     } else {
         $options = UrlHelper::parse($next_destination);
         if ($destinations) {
             $options['query']['destinations'] = $destinations;
         }
         // Redirect to any given path within the same domain.
         // @todo Revisit this in https://www.drupal.org/node/2418219.
         $next_destination = Url::fromUserInput('/' . $options['path']);
     }
     return $next_destination;
 }
예제 #11
0
 /**
  * Returns the next redirect path in a multipage sequence.
  *
  * @param array $destinations
  *   An array of destinations to redirect to.
  *
  * @return \Drupal\Core\Url
  *   The next destination to redirect to.
  */
 public static function getNextDestination(array $destinations)
 {
     $next_destination = array_shift($destinations);
     if (is_array($next_destination)) {
         $next_destination['options']['query']['destinations'] = $destinations;
         $next_destination += array('route_parameters' => array());
         $next_destination = Url::fromRoute($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']);
     } else {
         $options = UrlHelper::parse($next_destination);
         if ($destinations) {
             $options['query']['destinations'] = $destinations;
         }
         // Redirect to any given path within the same domain.
         // @todo Use Url::fromPath() once https://www.drupal.org/node/2351379 is
         //   resolved.
         $next_destination = Url::fromUri('base://' . $options['path']);
     }
     return $next_destination;
 }
 /**
  * Allows manipulation of the response object when performing a redirect.
  *
  * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
  *   The Event to process.
  */
 public function checkRedirectUrl(FilterResponseEvent $event)
 {
     $response = $event->getResponse();
     if ($response instanceof RedirectResponse) {
         $options = array();
         $request = $event->getRequest();
         $destination = $request->query->get('destination');
         // A destination from \Drupal::request()->query always overrides the
         // current RedirectResponse. We do not allow absolute URLs to be passed
         // via \Drupal::request()->query, as this can be an attack vector, with
         // the following exception:
         // - Absolute URLs that point to this site (i.e. same base URL and
         //   base path) are allowed.
         if ($destination) {
             if (!UrlHelper::isExternal($destination)) {
                 // The destination query parameter can be a relative URL in the sense
                 // of not including the scheme and host, but its path is expected to
                 // be absolute (start with a '/'). For such a case, prepend the
                 // scheme and host, because the 'Location' header must be absolute.
                 if (strpos($destination, '/') === 0) {
                     $destination = $request->getSchemeAndHttpHost() . $destination;
                 } else {
                     // Legacy destination query parameters can be relative paths that
                     // have not yet been converted to URLs (outbound path processors
                     // and other URL handling still needs to be performed).
                     // @todo As generateFromPath() is deprecated, remove this in
                     //   https://www.drupal.org/node/2418219.
                     $destination = UrlHelper::parse($destination);
                     $path = $destination['path'];
                     $options['query'] = $destination['query'];
                     $options['fragment'] = $destination['fragment'];
                     // The 'Location' HTTP header must always be absolute.
                     $options['absolute'] = TRUE;
                     $destination = $this->urlGenerator->generateFromPath($path, $options);
                 }
                 $response->setTargetUrl($destination);
             } elseif (UrlHelper::externalIsLocal($destination, $this->requestContext->getCompleteBaseUrl())) {
                 $response->setTargetUrl($destination);
             }
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function viewElements(FieldItemListInterface $items, $langcode)
 {
     // Define element array.
     $element = [];
     foreach ($items as $delta => $item) {
         // Convert the link-field item to a \Drupal\Core\Url object.
         $url = $this->buildUrl($item);
         // Parse the URL so we can check if the path contains a Github Gist. We do
         // this to check if we should actually render the element or provide a
         // notice in the log.
         $url = UrlHelper::parse($url->getUri());
         if (FALSE !== Unicode::strpos($url['path'], 'gist.github.com')) {
             $element[$delta] = ['#theme' => 'gist_embed', '#url' => $url];
         } else {
             $entity = $items->getEntity();
             $message = $this->t('The entity type: "@type" with the ID: "@id" is trying to use a link that isn\'t a Github Gist link for the Gist Embed Formatter.', array('@type' => ucfirst($entity->getEntityType()->id()), '@id' => $entity->id()));
             \Drupal::logger('gist_embed')->notice($message);
         }
     }
     return $element;
 }
예제 #14
0
 /**
  * Builds the cancel link for a confirmation form.
  *
  * @param \Drupal\Core\Form\ConfirmFormInterface $form
  *   The confirmation form.
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request.
  *
  * @return array
  *   The link render array for the cancel form.
  */
 public static function buildCancelLink(ConfirmFormInterface $form, Request $request)
 {
     // Prepare cancel link.
     $query = $request->query;
     $url = NULL;
     // If a destination is specified, that serves as the cancel link.
     if ($query->has('destination')) {
         $options = UrlHelper::parse($query->get('destination'));
         // @todo Revisit this in https://www.drupal.org/node/2418219.
         try {
             $url = Url::fromUserInput('/' . ltrim($options['path'], '/'), $options);
         } catch (\InvalidArgumentException $e) {
             // Suppress the exception and fall back to the form's cancel url.
         }
     }
     // Check for a route-based cancel link.
     if (!$url) {
         $url = $form->getCancelUrl();
     }
     return ['#type' => 'link', '#title' => $form->getCancelText(), '#attributes' => ['class' => ['button']], '#url' => $url];
 }
 /**
  * Allows manipulation of the response object when performing a redirect.
  *
  * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
  *   The Event to process.
  */
 public function checkRedirectUrl(FilterResponseEvent $event)
 {
     $response = $event->getResponse();
     if ($response instanceof RedirectResponse) {
         $options = array();
         $destination = $event->getRequest()->query->get('destination');
         // A destination from \Drupal::request()->query always overrides the
         // current RedirectResponse. We do not allow absolute URLs to be passed
         // via \Drupal::request()->query, as this can be an attack vector, with
         // the following exception:
         // - Absolute URLs that point to this site (i.e. same base URL and
         //   base path) are allowed.
         if ($destination && (!UrlHelper::isExternal($destination) || UrlHelper::externalIsLocal($destination, $GLOBALS['base_url']))) {
             $destination = UrlHelper::parse($destination);
             $path = $destination['path'];
             $options['query'] = $destination['query'];
             $options['fragment'] = $destination['fragment'];
             // The 'Location' HTTP header must always be absolute.
             $options['absolute'] = TRUE;
             $response->setTargetUrl($this->urlGenerator->generateFromPath($path, $options));
         }
     }
 }
예제 #16
0
  /**
   * Render this field as a link, with the info from a fieldset set by
   * the user.
   */
  protected function renderAsLink($alter, $text, $tokens) {
    $options = array(
      '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 SafeMarkup::checkPlain().
      $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 (strpos($path, base_path()) === 0) {
        $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) && strpos($path, '/') !== 0) {
        // 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, array('#' . $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'] = array($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 = array();
      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);

  }
예제 #17
0
 /**
  * {@inheritdoc}
  */
 public function massageFormValues(array $values, array $form, array &$form_state)
 {
     foreach ($values as &$value) {
         if (!empty($value['url'])) {
             try {
                 $parsed_url = UrlHelper::parse($value['url']);
                 // If internal links are supported, look up whether the given value is
                 // a path alias and store the system path instead.
                 if ($this->supportsInternalLinks() && !UrlHelper::isExternal($value['url'])) {
                     $parsed_url['path'] = \Drupal::service('path.alias_manager')->getPathByAlias($parsed_url['path']);
                 }
                 $url = Url::createFromPath($parsed_url['path']);
                 $url->setOption('query', $parsed_url['query']);
                 $url->setOption('fragment', $parsed_url['fragment']);
                 $url->setOption('attributes', $value['attributes']);
                 $value += $url->toArray();
                 // Reset the URL value to contain only the path.
                 $value['url'] = $parsed_url['path'];
             } catch (NotFoundHttpException $e) {
                 // Nothing to do here, LinkTypeConstraintValidator emits errors.
             } catch (MatchingRouteNotFoundException $e) {
                 // Nothing to do here, LinkTypeConstraintValidator emits errors.
             } catch (ParamNotConvertedException $e) {
                 // Nothing to do here, LinkTypeConstraintValidator emits errors.
             }
         }
     }
     return $values;
 }
예제 #18
0
 /**
  * Validates the path of the display.
  *
  * @param string $path
  *   The path to validate.
  *
  * @return array
  *   A list of error strings.
  */
 protected function validatePath($path)
 {
     $errors = array();
     if (strpos($path, '%') === 0) {
         $errors[] = $this->t('"%" may not be used for the first segment of a path.');
     }
     $parsed_url = UrlHelper::parse($path);
     if (empty($parsed_url['path'])) {
         $errors[] = $this->t('Path is empty.');
     }
     if (!empty($parsed_url['query'])) {
         $errors[] = $this->t('No query allowed.');
     }
     if (!parse_url('internal:/' . $path)) {
         $errors[] = $this->t('Invalid path. Valid characters are alphanumerics as well as "-", ".", "_" and "~".');
     }
     $path_sections = explode('/', $path);
     // Symfony routing does not allow to use numeric placeholders.
     // @see \Symfony\Component\Routing\RouteCompiler
     $numeric_placeholders = array_filter($path_sections, function ($section) {
         return preg_match('/^%(.*)/', $section, $matches) && is_numeric($matches[1]);
     });
     if (!empty($numeric_placeholders)) {
         $errors[] = $this->t("Numeric placeholders may not be used. Please use plain placeholders (%).");
     }
     return $errors;
 }
예제 #19
0
 /**
  * {@inheritdoc}
  */
 public function validateForm(array &$form, FormStateInterface $form_state)
 {
     parent::validateForm($form, $form_state);
     $source = $form_state->getValue(array('redirect_source', 0));
     $redirect = $form_state->getValue(array('redirect_redirect', 0));
     if ($source['path'] == '<front>') {
         $form_state->setErrorByName('redirect_source', t('It is not allowed to create a redirect from the front page.'));
     }
     if (strpos($source['path'], '#') !== FALSE) {
         $form_state->setErrorByName('redirect_source', t('The anchor fragments are not allowed.'));
     }
     if (strpos($source['path'], '/') === 0) {
         $form_state->setErrorByName('redirect_source', t('The url to redirect from should not start with a forward slash (/).'));
     }
     try {
         $source_url = Url::fromUri('internal:/' . $source['path']);
         $redirect_url = Url::fromUri($redirect['uri']);
         // It is relevant to do this comparison only in case the source path has
         // a valid route. Otherwise the validation will fail on the redirect path
         // being an invalid route.
         if ($source_url->toString() == $redirect_url->toString()) {
             $form_state->setErrorByName('redirect_redirect', t('You are attempting to redirect the page to itself. This will result in an infinite loop.'));
         }
     } catch (\InvalidArgumentException $e) {
         // Do nothing, we want to only compare the resulting URLs.
     }
     $parsed_url = UrlHelper::parse(trim($source['path']));
     $path = isset($parsed_url['path']) ? $parsed_url['path'] : NULL;
     $query = isset($parsed_url['query']) ? $parsed_url['query'] : NULL;
     $hash = Redirect::generateHash($path, $query, $form_state->getValue('language')[0]['value']);
     // Search for duplicate.
     $redirects = \Drupal::entityManager()->getStorage('redirect')->loadByProperties(array('hash' => $hash));
     if (!empty($redirects)) {
         $redirect = array_shift($redirects);
         if ($this->entity->isNew() || $redirect->id() != $this->entity->id()) {
             $form_state->setErrorByName('redirect_source', t('The source path %source is already being redirected. Do you want to <a href="@edit-page">edit the existing redirect</a>?', array('%source' => $source['path'], '@edit-page' => $redirect->url('edit-form'))));
         }
     }
 }
예제 #20
0
 /**
  * Converts the passed in destination into an absolute URL.
  *
  * @param string $destination
  *   The path for the destination. In case it starts with a slash it should
  *   have the base path included already.
  * @param string $scheme_and_host
  *   The scheme and host string of the current request.
  *
  * @return string
  *   The destination as absolute URL.
  */
 protected function getDestinationAsAbsoluteUrl($destination, $scheme_and_host)
 {
     if (!UrlHelper::isExternal($destination)) {
         // The destination query parameter can be a relative URL in the sense of
         // not including the scheme and host, but its path is expected to be
         // absolute (start with a '/'). For such a case, prepend the scheme and
         // host, because the 'Location' header must be absolute.
         if (strpos($destination, '/') === 0) {
             $destination = $scheme_and_host . $destination;
         } else {
             // Legacy destination query parameters can be internal paths that have
             // not yet been converted to URLs.
             $destination = UrlHelper::parse($destination);
             $uri = 'base:' . $destination['path'];
             $options = ['query' => $destination['query'], 'fragment' => $destination['fragment'], 'absolute' => TRUE];
             // Treat this as if it's user input of a path relative to the site's
             // base URL.
             $destination = $this->unroutedUrlAssembler->assemble($uri, $options);
         }
     }
     return $destination;
 }
예제 #21
0
 /**
  * Tests using entity fields of the link field type.
  */
 public function testLinkItem()
 {
     // Create entity.
     $entity = entity_create('entity_test');
     $url = 'https://www.drupal.org?test_param=test_value';
     $parsed_url = UrlHelper::parse($url);
     $title = $this->randomMachineName();
     $class = $this->randomMachineName();
     $entity->field_test->uri = $parsed_url['path'];
     $entity->field_test->title = $title;
     $entity->field_test->first()->get('options')->set('query', $parsed_url['query']);
     $entity->field_test->first()->get('options')->set('attributes', array('class' => $class));
     $entity->name->value = $this->randomMachineName();
     $entity->save();
     // Verify that the field value is changed.
     $id = $entity->id();
     $entity = entity_load('entity_test', $id);
     $this->assertTrue($entity->field_test instanceof FieldItemListInterface, 'Field implements interface.');
     $this->assertTrue($entity->field_test[0] instanceof FieldItemInterface, 'Field item implements interface.');
     $this->assertEqual($entity->field_test->uri, $parsed_url['path']);
     $this->assertEqual($entity->field_test[0]->uri, $parsed_url['path']);
     $this->assertEqual($entity->field_test->title, $title);
     $this->assertEqual($entity->field_test[0]->title, $title);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $class);
     $this->assertEqual($entity->field_test->options['query'], $parsed_url['query']);
     // Update only the entity name property to check if the link field data will
     // remain intact.
     $entity->name->value = $this->randomMachineName();
     $entity->save();
     $id = $entity->id();
     $entity = entity_load('entity_test', $id);
     $this->assertEqual($entity->field_test->uri, $parsed_url['path']);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $class);
     $this->assertEqual($entity->field_test->options['query'], $parsed_url['query']);
     // Verify changing the field value.
     $new_url = 'https://www.drupal.org';
     $new_title = $this->randomMachineName();
     $new_class = $this->randomMachineName();
     $entity->field_test->uri = $new_url;
     $entity->field_test->title = $new_title;
     $entity->field_test->first()->get('options')->set('query', NULL);
     $entity->field_test->first()->get('options')->set('attributes', array('class' => $new_class));
     $this->assertEqual($entity->field_test->uri, $new_url);
     $this->assertEqual($entity->field_test->title, $new_title);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $new_class);
     $this->assertNull($entity->field_test->options['query']);
     // Read changed entity and assert changed values.
     $entity->save();
     $entity = entity_load('entity_test', $id);
     $this->assertEqual($entity->field_test->uri, $new_url);
     $this->assertEqual($entity->field_test->title, $new_title);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $new_class);
     // Check that if we only set uri the default values for title and options
     // are also initialized.
     $entity->field_test = ['uri' => 'internal:/node/add'];
     $this->assertEqual($entity->field_test->uri, 'internal:/node/add');
     $this->assertNull($entity->field_test->title);
     $this->assertIdentical($entity->field_test->options, []);
     // Check that if set uri and serialize options then the default values are
     // properly initialized.
     $entity->field_test = ['uri' => 'internal:/node/add', 'options' => serialize(['query' => NULL])];
     $this->assertEqual($entity->field_test->uri, 'internal:/node/add');
     $this->assertNull($entity->field_test->title);
     $this->assertNull($entity->field_test->options['query']);
     // Check that if we set the direct value of link field it correctly set the
     // uri and the default values of the field.
     $entity->field_test = 'internal:/node/add';
     $this->assertEqual($entity->field_test->uri, 'internal:/node/add');
     $this->assertNull($entity->field_test->title);
     $this->assertIdentical($entity->field_test->options, []);
     // Check that setting LinkItem value NULL doesn't generate any error or
     // warning.
     $entity->field_test[0] = NULL;
     $this->assertNull($entity->field_test[0]->getValue());
     // Test the generateSampleValue() method for generic, external, and internal
     // link types.
     $entity = entity_create('entity_test');
     $entity->field_test->generateSampleItems();
     $entity->field_test_external->generateSampleItems();
     $entity->field_test_internal->generateSampleItems();
     $this->entityValidateAndSave($entity);
 }
예제 #22
0
 /**
  * Breaks up a user-entered URL or path into all the relevant parts.
  *
  * @param string $url
  *   The user-entered URL or path.
  *
  * @return array
  *   The extracted parts.
  */
 protected function extractUrl($url)
 {
     $extracted = UrlHelper::parse($url);
     $external = UrlHelper::isExternal($url);
     if ($external) {
         $extracted['url'] = $extracted['path'];
         $extracted['route_name'] = NULL;
         $extracted['route_parameters'] = array();
     } else {
         $extracted['url'] = '';
         // If the path doesn't match a Drupal path, the route should end up empty.
         $extracted['route_name'] = NULL;
         $extracted['route_parameters'] = array();
         try {
             // Find the route_name.
             $normal_path = $this->pathAliasManager->getPathByAlias($extracted['path']);
             $url_obj = Url::createFromPath($normal_path);
             $extracted['route_name'] = $url_obj->getRouteName();
             $extracted['route_parameters'] = $url_obj->getRouteParameters();
         } catch (MatchingRouteNotFoundException $e) {
             // The path doesn't match a Drupal path.
         } catch (ParamNotConvertedException $e) {
             // A path like node/99 matched a route, but the route parameter was
             // invalid (e.g. node with ID 99 does not exist).
         }
     }
     return $extracted;
 }
예제 #23
0
파일: UrlTest.php 프로젝트: 318io/318-io
 /**
  * Tests the fromUserInput method with valid paths.
  *
  * @covers ::fromUserInput
  * @dataProvider providerFromValidInternalUri
  */
 public function testFromUserInput($path)
 {
     $url = Url::fromUserInput($path);
     $uri = $url->getUri();
     $this->assertInstanceOf('Drupal\\Core\\Url', $url);
     $this->assertFalse($url->isRouted());
     $this->assertEquals(0, strpos($uri, 'base:'));
     $parts = UrlHelper::parse($path);
     $options = $url->getOptions();
     if (!empty($parts['fragment'])) {
         $this->assertSame($parts['fragment'], $options['fragment']);
     } else {
         $this->assertArrayNotHasKey('fragment', $options);
     }
     if (!empty($parts['query'])) {
         $this->assertEquals($parts['query'], $options['query']);
     } else {
         $this->assertArrayNotHasKey('query', $options);
     }
 }
예제 #24
0
 /**
  * Tests url parsing.
  *
  * @dataProvider providerTestParse
  * @covers ::parse
  *
  * @param string $url
  *   URL to test.
  * @param array $expected
  *   Associative array with expected parameters.
  */
 public function testParse($url, $expected)
 {
     $parsed = UrlHelper::parse($url);
     $this->assertEquals($expected, $parsed, 'The url was not properly parsed.');
 }
예제 #25
0
 /**
  * {@inheritdoc}
  */
 public function submitForm(array &$form, FormStateInterface $form_state)
 {
     $cart_links_config = $this->config('uc_cart_links.settings');
     $actions = explode('-', urldecode($this->actions));
     $rebuild_cart = FALSE;
     $messages = array();
     $id = $this->t('(not specified)');
     $cart = Cart::create(\Drupal::getContainer());
     foreach ($actions as $action) {
         switch (Unicode::substr($action, 0, 1)) {
             // Set the ID of the Cart Link.
             case 'i':
             case 'I':
                 $id = Unicode::substr($action, 1, 32);
                 break;
                 // Add a product to the cart.
             // Add a product to the cart.
             case 'p':
             case 'P':
                 // Set the default product variables.
                 $p = array('nid' => 0, 'qty' => 1, 'data' => array());
                 $msg = TRUE;
                 // Parse the product action to adjust the product variables.
                 $parts = explode('_', $action);
                 foreach ($parts as $part) {
                     switch (Unicode::substr($part, 0, 1)) {
                         // Set the product node ID: p23
                         case 'p':
                         case 'P':
                             $p['nid'] = intval(Unicode::substr($part, 1));
                             break;
                             // Set the quantity to add to cart: _q2
                         // Set the quantity to add to cart: _q2
                         case 'q':
                         case 'Q':
                             $p['qty'] = intval(Unicode::substr($part, 1));
                             break;
                             // Set an attribute/option for the product: _a3o6
                         // Set an attribute/option for the product: _a3o6
                         case 'a':
                         case 'A':
                             $attribute = intval(Unicode::substr($part, 1, stripos($part, 'o') - 1));
                             $option = (string) Unicode::substr($part, stripos($part, 'o') + 1);
                             if (!isset($p['attributes'][$attribute])) {
                                 $p['attributes'][$attribute] = $option;
                             } else {
                                 // Multiple options for this attribute implies checkbox
                                 // attribute, which we must store as an array
                                 if (is_array($p['attributes'][$attribute])) {
                                     // Already an array, just append this new option
                                     $p['attributes'][$attribute][$option] = $option;
                                 } else {
                                     // Set but not an array, means we already have at least one
                                     // option, so put that into an array with this new option
                                     $p['attributes'][$attribute] = array($p['attributes'][$attribute] => $p['attributes'][$attribute], $option => $option);
                                 }
                             }
                             break;
                             // Suppress the add to cart message: _s
                         // Suppress the add to cart message: _s
                         case 's':
                         case 'S':
                             $msg = FALSE;
                             break;
                     }
                 }
                 // Add the item to the cart, suppressing the default redirect.
                 if ($p['nid'] > 0 && $p['qty'] > 0) {
                     // If it's a product kit, we need black magic to make everything work
                     // right. In other words, we have to simulate FAPI's form values.
                     $node = node_load($p['nid']);
                     if ($node->status) {
                         if (isset($node->products) && is_array($node->products)) {
                             foreach ($node->products as $nid => $product) {
                                 $p['data']['products'][$nid] = array('nid' => $nid, 'qty' => $product->qty);
                             }
                         }
                         $cart->addItem($p['nid'], $p['qty'], $p['data'] + \Drupal::moduleHandler()->invokeAll('uc_add_to_cart_data', array($p)), NULL, $msg, FALSE, FALSE);
                         $rebuild_cart = TRUE;
                     } else {
                         $this->logger('uc_cart_link')->error('Cart Link on %url tried to add an unpublished product to the cart.', array('%url' => $this->getRequest()->server->get('HTTP_REFERER')));
                     }
                 }
                 break;
                 // Empty the shopping cart.
             // Empty the shopping cart.
             case 'e':
             case 'E':
                 if ($cart_links_config->get('empty')) {
                     $cart->emptyCart();
                 }
                 break;
                 // Display a pre-configured message.
             // Display a pre-configured message.
             case 'm':
             case 'M':
                 // Load the messages if they haven't been loaded yet.
                 if (empty($messages)) {
                     $data = explode("\n", $cart_links_config->get('messages'));
                     foreach ($data as $message) {
                         list($mkey, $mdata) = explode('|', $message, 2);
                         $messages[trim($mkey)] = trim($mdata);
                     }
                 }
                 // Parse the message key and display it if it exists.
                 $mkey = intval(Unicode::substr($action, 1));
                 if (!empty($messages[$mkey])) {
                     drupal_set_message($messages[$mkey]);
                 }
                 break;
         }
         // Rebuild the cart cache if necessary.
         if ($rebuild_cart) {
             $cart->getContents(NULL, 'rebuild');
         }
     }
     if ($cart_links_config->get('track')) {
         db_merge('uc_cart_link_clicks')->key(array('cart_link_id' => (string) $id))->fields(array('clicks' => 1, 'last_click' => REQUEST_TIME))->expression('clicks', 'clicks + :i', array(':i' => 1))->execute();
     }
     $_SESSION['uc_cart_last_url'] = $this->getRequest()->server->get('HTTP_REFERER');
     $query = $this->getRequest()->query;
     if ($query->has('destination')) {
         $options = UrlHelper::parse($query->get('destination'));
         $path = $options['path'];
     } else {
         $path = 'cart';
         $options = array();
     }
     $options += array('absolute' => TRUE);
     // Form redirect is for confirmed links.
     $form_state->setRedirectUrl(Url::fromUri('base:/' . $path, $options));
 }
예제 #26
0
파일: WebTestBase.php 프로젝트: Wylbur/gj
 /**
  * Executes an Ajax form submission.
  *
  * This executes a POST as ajax.js does. The returned JSON data is used to
  * update $this->content via drupalProcessAjaxResponse(). It also returns
  * the array of AJAX commands received.
  *
  * @param \Drupal\Core\Url|string $path
  *   Location of the form containing the Ajax enabled element to test. Can be
  *   either a Drupal path or an absolute path or NULL to use the current page.
  * @param $edit
  *   Field data in an associative array. Changes the current input fields
  *   (where possible) to the values indicated.
  * @param $triggering_element
  *   The name of the form element that is responsible for triggering the Ajax
  *   functionality to test. May be a string or, if the triggering element is
  *   a button, an associative array where the key is the name of the button
  *   and the value is the button label. i.e.) array('op' => t('Refresh')).
  * @param $ajax_path
  *   (optional) Override the path set by the Ajax settings of the triggering
  *   element.
  * @param $options
  *   (optional) Options to be forwarded to the url generator.
  * @param $headers
  *   (optional) An array containing additional HTTP request headers, each
  *   formatted as "name: value". Forwarded to drupalPostForm().
  * @param $form_html_id
  *   (optional) HTML ID of the form to be submitted, use when there is more
  *   than one identical form on the same page and the value of the triggering
  *   element is not enough to identify the form. Note this is not the Drupal
  *   ID of the form but rather the HTML ID of the form.
  * @param $ajax_settings
  *   (optional) An array of Ajax settings which if specified will be used in
  *   place of the Ajax settings of the triggering element.
  *
  * @return
  *   An array of Ajax commands.
  *
  * @see drupalPostForm()
  * @see drupalProcessAjaxResponse()
  * @see ajax.js
  */
 protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_path = NULL, array $options = array(), array $headers = array(), $form_html_id = NULL, $ajax_settings = NULL)
 {
     // Get the content of the initial page prior to calling drupalPostForm(),
     // since drupalPostForm() replaces $this->content.
     if (isset($path)) {
         // Avoid sending the wrapper query argument to drupalGet so we can fetch
         // the form and populate the internal WebTest values.
         $get_options = $options;
         unset($get_options['query'][MainContentViewSubscriber::WRAPPER_FORMAT]);
         $this->drupalGet($path, $get_options);
     }
     $content = $this->content;
     $drupal_settings = $this->drupalSettings;
     // Provide a default value for the wrapper envelope.
     $options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] = isset($options['query'][MainContentViewSubscriber::WRAPPER_FORMAT]) ? $options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] : 'drupal_ajax';
     // Get the Ajax settings bound to the triggering element.
     if (!isset($ajax_settings)) {
         if (is_array($triggering_element)) {
             $xpath = '//*[@name="' . key($triggering_element) . '" and @value="' . current($triggering_element) . '"]';
         } else {
             $xpath = '//*[@name="' . $triggering_element . '"]';
         }
         if (isset($form_html_id)) {
             $xpath = '//form[@id="' . $form_html_id . '"]' . $xpath;
         }
         $element = $this->xpath($xpath);
         $element_id = (string) $element[0]['id'];
         $ajax_settings = $drupal_settings['ajax'][$element_id];
     }
     // Add extra information to the POST data as ajax.js does.
     $extra_post = array();
     if (isset($ajax_settings['submit'])) {
         foreach ($ajax_settings['submit'] as $key => $value) {
             $extra_post[$key] = $value;
         }
     }
     $extra_post[AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER] = 1;
     $extra_post += $this->getAjaxPageStatePostData();
     // Now serialize all the $extra_post values, and prepend it with an '&'.
     $extra_post = '&' . $this->serializePostValues($extra_post);
     // Unless a particular path is specified, use the one specified by the
     // Ajax settings.
     if (!isset($ajax_path)) {
         if (isset($ajax_settings['url'])) {
             // In order to allow to set for example the wrapper envelope query
             // parameter we need to get the system path again.
             $parsed_url = UrlHelper::parse($ajax_settings['url']);
             $options['query'] = $parsed_url['query'] + $options['query'];
             $options += ['fragment' => $parsed_url['fragment']];
             // We know that $parsed_url['path'] is already with the base path
             // attached.
             $ajax_path = preg_replace('/^' . preg_quote(base_path(), '/') . '/', '', $parsed_url['path']);
         }
     }
     if (empty($ajax_path)) {
         throw new \Exception('No #ajax path specified.');
     }
     $ajax_path = $this->container->get('unrouted_url_assembler')->assemble('base://' . $ajax_path, $options);
     // Submit the POST request.
     $return = Json::decode($this->drupalPostForm(NULL, $edit, array('path' => $ajax_path, 'triggering_element' => $triggering_element), $options, $headers, $form_html_id, $extra_post));
     if ($this->assertAjaxHeader) {
         $this->assertIdentical($this->drupalGetHeader('X-Drupal-Ajax-Token'), '1', 'Ajax response header found.');
     }
     // Change the page content by applying the returned commands.
     if (!empty($ajax_settings) && !empty($return)) {
         $this->drupalProcessAjaxResponse($content, $return, $ajax_settings, $drupal_settings);
     }
     $verbose = 'AJAX POST request to: ' . $path;
     $verbose .= '<br />AJAX controller path: ' . $ajax_path;
     $verbose .= '<hr />Ending URL: ' . $this->getUrl();
     $verbose .= '<hr />' . $this->content;
     $this->verbose($verbose);
     return $return;
 }
예제 #27
0
 /**
  * Tests UrlHelper::parse().
  */
 function testDrupalParseUrl()
 {
     // Relative, absolute, and external URLs, without/with explicit script path,
     // without/with Drupal path.
     foreach (array('', '/', 'http://drupal.org/') as $absolute) {
         foreach (array('', 'index.php/') as $script) {
             foreach (array('', 'foo/bar') as $path) {
                 $url = $absolute . $script . $path . '?foo=bar&bar=baz&baz#foo';
                 $expected = array('path' => $absolute . $script . $path, 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''), 'fragment' => 'foo');
                 $this->assertEqual(UrlHelper::parse($url), $expected, 'URL parsed correctly.');
             }
         }
     }
     // Relative URL that is known to confuse parse_url().
     $url = 'foo/bar:1';
     $result = array('path' => 'foo/bar:1', 'query' => array(), 'fragment' => '');
     $this->assertEqual(UrlHelper::parse($url), $result, 'Relative URL parsed correctly.');
     // Test that drupal can recognize an absolute URL. Used to prevent attack vectors.
     $url = 'http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo';
     $this->assertTrue(UrlHelper::isExternal($url), 'Correctly identified an external URL.');
     // Test that UrlHelper::parse() does not allow spoofing a URL to force a malicious redirect.
     $parts = UrlHelper::parse('forged:http://cwe.mitre.org/data/definitions/601.html');
     $this->assertFalse(UrlHelper::isValid($parts['path'], TRUE), '\\Drupal\\Component\\Utility\\UrlHelper::isValid() correctly parsed a forged URL.');
 }
예제 #28
0
 /**
  * Render this field as a link, with the info from a fieldset set by
  * the user.
  */
 protected function renderAsLink($alter, $text, $tokens)
 {
     $options = array('absolute' => !empty($alter['absolute']) ? TRUE : FALSE, 'alias' => FALSE, 'entity' => NULL, 'entity_type' => NULL, 'fragment' => NULL, 'language' => NULL, 'query' => []);
     $alter += ['path' => NULL];
     $path = $alter['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();
     // strip_tags() removes <front>, so check whether its different to front.
     if ($path != 'route:<front>') {
         // Unescape Twig delimiters that may have been escaped by the
         // Url::toUriString() call above, because we support twig tokens in
         // rewrite settings of views fields.
         // In that case the original path looks like
         // internal:/admin/content/files/usage/{{ fid }}, which will be escaped by
         // the toUriString() call above.
         $path = preg_replace(['/(\\%7B){2}(\\%20)*/', '/(\\%20)*(\\%7D){2}/'], ['{{', '}}'], $path);
         // Use strip tags as there should never be HTML in the path.
         // However, we need to preserve special characters like " that
         // were removed by SafeMarkup::checkPlain().
         $path = strip_tags(Html::decodeEntities($this->viewsTokenReplace($path, $tokens)));
         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 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 on for external URLs.
     if ($alter['external']) {
         if (!isset($url['scheme'])) {
             // There is no scheme, add the default 'http://' to the $path.
             // Use the original $alter['path'] instead of the parsed version.
             $path = "http://" . $alter['path'];
             // Reset the $url array to include the new scheme.
             $url = UrlHelper::parse($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, array('#' . $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'] = array($class);
     }
     if (!empty($alter['rel']) && ($rel = $this->viewsTokenReplace($alter['rel'], $tokens))) {
         $options['attributes']['rel'] = $rel;
     }
     // Not sure if this SafeMarkup::checkPlain() is needed here?
     $target = SafeMarkup::checkPlain(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 _l().
         $options['query'] = UrlHelper::buildQuery($alter['query']);
         $options['query'] = $this->viewsTokenReplace($options['query'], $tokens);
         $query = array();
         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
     $value = '';
     if (!empty($alter['prefix'])) {
         $value .= Xss::filterAdmin($this->viewsTokenReplace($alter['prefix'], $tokens));
     }
     $value .= $this->linkGenerator()->generate($text, $final_url);
     if (!empty($alter['suffix'])) {
         $value .= Xss::filterAdmin($this->viewsTokenReplace($alter['suffix'], $tokens));
     }
     return $value;
 }
예제 #29
0
 /**
  * Builds the $form['#action'].
  *
  * @return string
  *   The URL to be used as the $form['#action'].
  */
 protected function buildFormAction()
 {
     // @todo Use <current> instead of the master request in
     //   https://www.drupal.org/node/2505339.
     $request = $this->requestStack->getMasterRequest();
     $request_uri = $request->getRequestUri();
     // Prevent cross site requests via the Form API by using an absolute URL
     // when the request uri starts with multiple slashes..
     if (strpos($request_uri, '//') === 0) {
         $request_uri = $request->getUri();
     }
     // @todo Remove this parsing once these are removed from the request in
     //   https://www.drupal.org/node/2504709.
     $parsed = UrlHelper::parse($request_uri);
     unset($parsed['query'][static::AJAX_FORM_REQUEST], $parsed['query'][MainContentViewSubscriber::WRAPPER_FORMAT]);
     return $parsed['path'] . ($parsed['query'] ? '?' . UrlHelper::buildQuery($parsed['query']) : '');
 }
예제 #30
-1
 /**
  * Tests using entity fields of the link field type.
  */
 public function testLinkItem()
 {
     // Create entity.
     $entity = entity_create('entity_test');
     $url = 'http://www.drupal.org?test_param=test_value';
     $parsed_url = UrlHelper::parse($url);
     $title = $this->randomMachineName();
     $class = $this->randomMachineName();
     $entity->field_test->uri = $parsed_url['path'];
     $entity->field_test->title = $title;
     $entity->field_test->first()->get('options')->set('query', $parsed_url['query']);
     $entity->field_test->first()->get('options')->set('attributes', array('class' => $class));
     $entity->name->value = $this->randomMachineName();
     $entity->save();
     // Verify that the field value is changed.
     $id = $entity->id();
     $entity = entity_load('entity_test', $id);
     $this->assertTrue($entity->field_test instanceof FieldItemListInterface, 'Field implements interface.');
     $this->assertTrue($entity->field_test[0] instanceof FieldItemInterface, 'Field item implements interface.');
     $this->assertEqual($entity->field_test->uri, $parsed_url['path']);
     $this->assertEqual($entity->field_test[0]->uri, $parsed_url['path']);
     $this->assertEqual($entity->field_test->title, $title);
     $this->assertEqual($entity->field_test[0]->title, $title);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $class);
     $this->assertEqual($entity->field_test->options['query'], $parsed_url['query']);
     // Update only the entity name property to check if the link field data will
     // remain intact.
     $entity->name->value = $this->randomMachineName();
     $entity->save();
     $id = $entity->id();
     $entity = entity_load('entity_test', $id);
     $this->assertEqual($entity->field_test->uri, $parsed_url['path']);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $class);
     $this->assertEqual($entity->field_test->options['query'], $parsed_url['query']);
     // Verify changing the field value.
     $new_url = 'http://drupal.org';
     $new_title = $this->randomMachineName();
     $new_class = $this->randomMachineName();
     $entity->field_test->uri = $new_url;
     $entity->field_test->title = $new_title;
     $entity->field_test->first()->get('options')->set('query', NULL);
     $entity->field_test->first()->get('options')->set('attributes', array('class' => $new_class));
     $this->assertEqual($entity->field_test->uri, $new_url);
     $this->assertEqual($entity->field_test->title, $new_title);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $new_class);
     $this->assertNull($entity->field_test->options['query']);
     // Read changed entity and assert changed values.
     $entity->save();
     $entity = entity_load('entity_test', $id);
     $this->assertEqual($entity->field_test->uri, $new_url);
     $this->assertEqual($entity->field_test->title, $new_title);
     $this->assertEqual($entity->field_test->options['attributes']['class'], $new_class);
     // Test the generateSampleValue() method.
     $entity = entity_create('entity_test');
     $entity->field_test->generateSampleItems();
     $this->entityValidateAndSave($entity);
 }