You are here

class ForwardForm in Forward 8

Same name in this branch
  1. 8 src/Form/ForwardForm.php \Drupal\forward\Form\ForwardForm
  2. 8 src/Plugin/DsField/ForwardForm.php \Drupal\forward\Plugin\DsField\ForwardForm
Same name and namespace in other branches
  1. 8.3 src/Form/ForwardForm.php \Drupal\forward\Form\ForwardForm
  2. 8.2 src/Form/ForwardForm.php \Drupal\forward\Form\ForwardForm
  3. 4.x src/Form/ForwardForm.php \Drupal\forward\Form\ForwardForm
  4. 4.0.x src/Form/ForwardForm.php \Drupal\forward\Form\ForwardForm

Forward a page to a friend

Hierarchy

Expanded class hierarchy of ForwardForm

1 file declares its use of ForwardForm
ForwardFormBuilder.php in src/ForwardFormBuilder.php

File

src/Form/ForwardForm.php, line 30

Namespace

Drupal\forward\Form
View source
class ForwardForm extends FormBase implements BaseFormIdInterface {

  /**
   * The entity being forwarded.
   *
   * @var Drupal\Core\Entity\EntityInterface
   */
  protected $entity;

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * The token service.
   *
   * @var \Drupal\Core\Utility\Token
   */
  protected $tokenService;

  /**
   * The flood interface.
   *
   * @var \Drupal\Core\Flood\FloodInterface
   */
  protected $floodInterface;

  /**
   * The account switcher service.
   *
   * @var \Drupal\Core\Session\AccountSwitcherInterface
   */
  protected $accountSwitcher;

  /**
   * The render service.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * The event dispatcher service.
   *
   * @var \Symfony\Component\EventDispatcher;
   */
  protected $eventDispatcher;

  /**
   * The mail service.
   *
   * @var \Drupal\Core\Mail\MailManager
   */
  protected $mailer;

  /**
   * The link generation service.
   *
   * @var \Drupal\Core\Utility\LinkGenerator
   */
  protected $linkGenerator;

  /**
   * The settings for this form.
   *
   * @var array
   */
  protected $settings;

  /**
   * Constructs a Forward Form.
   *
   * @param Drupal\Core\Entity\EntityInterface $entity
   *   The entity being forwarded.
   */
  public function __construct(EntityInterface $entity) {
    $this->entity = $entity;
  }

  /**
   * Inject services.
   *
   * @param \Drupal\Core\Extension\ModuleHandlerInterface
   *   The module handler service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface
   *   The entity type manager.
   * @param \Symfony\Component\HttpFoundation\RequestStack
   *   The request stack.
   * @param \Drupal\Core\Database\Connection
   *   The database connection.
   * @param \Drupal\Core\Utility\Token
   *   The token service.
   * @param \Drupal\Core\Flood\FloodInterface
   *   The flood interface.
   * @param \Drupal\Core\Session\AccountSwitcherInterface
   *   The account switcher service.
   * @param \Drupal\Core\Render\RendererInterface
   *   The render service.
   * @param \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
   *   The event dispatcher service.
   * @param \Drupal\Core\Mail\MailManager
   *   The mail service.
   * @param \Drupal\Core\Utility\LinkGenerator
   *   The link generation service.
   */
  public function injectServices(ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, RequestStack $request_stack, Connection $database, Token $token_service, FloodInterface $flood_interface, AccountSwitcherInterface $account_switcher, RendererInterface $renderer, ContainerAwareEventDispatcher $event_dispatcher, MailManager $mailer, LinkGenerator $link_generator) {
    $this->moduleHandler = $module_handler;
    $this->entityTypeManager = $entity_type_manager;
    $this->requestStack = $request_stack;
    $this->database = $database;
    $this->tokenService = $token_service;
    $this->floodInterface = $flood_interface;
    $this->accountSwitcher = $account_switcher;
    $this->renderer = $renderer;
    $this->eventDispatcher = $event_dispatcher;
    $this->mailer = $mailer;
    $this->linkGenerator = $link_generator;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'forward_form_' . $this->entity
      ->getEntityTypeId() . '_' . $this->entity
      ->id();
  }

  /**
   * {@inheritdoc}
   */
  public function getBaseFormId() {
    return 'forward_form';
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return [
      'forward.form',
    ];
  }

  /**
   * Clean a string
   */
  private function cleanString($string) {

    // Strip embedded URLs
    $string = preg_replace('|https?://www\\.[a-z\\.0-9]+|i', '', $string);
    $string = preg_replace('|www\\.[a-z\\.0-9]+|i', '', $string);
    return $string;
  }

  /**
   * Get a token
   */
  private function getToken(FormStateInterface $form_state = NULL) {
    $token = array();
    if ($form_state && $form_state
      ->getValue('name')) {

      // Harden the name field against abuse. @see https://www.drupal.org/node/2793891
      $token = [
        'forward' => [
          'sender_name' => $this
            ->cleanString($form_state
            ->getValue('name')),
        ],
      ];
    }
    elseif ($this
      ->currentUser()
      ->isAuthenticated()) {
      $token = [
        'forward' => [
          'sender_name' => $this
            ->currentUser()
            ->getDisplayName(),
        ],
      ];
    }
    if ($form_state && $form_state
      ->getValue('email')) {
      $token['forward']['sender_email'] = $form_state
        ->getValue('email');
    }
    elseif ($this
      ->currentUser()
      ->isAuthenticated()) {
      $token['forward']['sender_email'] = $this
        ->currentUser()
        ->getEmail();
    }
    if ($form_state) {
      $token['forward']['entity'] = $form_state
        ->get('#entity');
    }

    // Allow other modules to add more tokens
    if ($extra_tokens = $this->moduleHandler
      ->invokeAll('forward_token', array(
      $form_state,
    ))) {
      $token += $extra_tokens;
    }
    return $token;
  }

  /**
   * Get the event name used for Flood control
   */
  private function getFloodControlEventName() {
    return 'forward.send';
  }

  /**
   * Determine if a given display is valid for an entity
   */
  private function isValidDisplay(EntityInterface $entity, $view_mode) {

    // Assume the display is valid
    $valid = TRUE;

    // Build display name
    if ($entity
      ->getEntityType()
      ->hasKey('bundle')) {

      // Bundled entity types, e.g. node
      $display_name = $entity
        ->getEntityTypeId() . '.' . $entity
        ->bundle() . '.' . $view_mode;
    }
    else {

      // Entity types without bundles, e.g. user
      $display_name = $entity
        ->getEntityTypeId() . '.' . $view_mode;
    }

    // Attempt load
    $display = $this->entityTypeManager
      ->getStorage('entity_view_display')
      ->load($display_name);
    if ($display) {

      // If the display loads, it exists in configuration, and status can be checked
      $valid = FALSE;
      if ($display
        ->status()) {
        $valid = TRUE;
      }
    }
    return $valid;
  }

  /**
   * Logging
   */
  private function logEvent(EntityInterface $entity) {
    $entity_type = $entity
      ->getEntityTypeId();
    $bundle = $entity
      ->bundle();
    $entity_id = $entity
      ->id();
    $uid = $this
      ->currentUser()
      ->id();
    $path = substr($entity
      ->toUrl()
      ->toString(), 1);
    $ip_address = $this->requestStack
      ->getCurrentRequest()
      ->getClientIp();
    $timestamp = REQUEST_TIME;

    // Insert into log
    $this->database
      ->insert('forward_log')
      ->fields(array(
      'type' => $entity_type,
      'id' => $entity_id,
      'path' => $path,
      'action' => 'SENT',
      'timestamp' => $timestamp,
      'uid' => $uid,
      'hostname' => $ip_address,
    ))
      ->execute();

    // Update statistics
    $this->database
      ->merge('forward_statistics')
      ->key(array(
      'type' => $entity_type,
      'bundle' => $bundle,
      'id' => $entity_id,
    ))
      ->fields(array(
      'forward_count' => 1,
      'last_forward_timestamp' => $timestamp,
    ))
      ->expression('forward_count', 'forward_count + 1')
      ->execute();
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, array $settings = NULL) {
    if (!$settings) {
      $settings = $this
        ->config('forward.settings')
        ->get();
    }
    $this->settings = $settings;
    $form_state
      ->set('#entity', $this->entity);
    $token = $this
      ->getToken($form_state);
    $langcode = $this->entity
      ->language()
      ->getId();

    // Build the form
    if ($settings['forward_interface_type'] == 'link') {

      // Set the page title dynamically
      $form['#title'] = $this->tokenService
        ->replace($settings['forward_link_title'], $token, array(
        'langcode' => $langcode,
      ));
    }
    else {

      // Inline form
      $form['message'] = array(
        '#type' => 'details',
        '#title' => $this->tokenService
          ->replace($settings['forward_link_title'], $token, array(
          'langcode' => $langcode,
        )),
        '#description' => '',
        '#open' => FALSE,
        '#weight' => $settings['forward_interface_weight'],
      );
    }
    $form['message']['instructions'] = array(
      '#markup' => $this->tokenService
        ->replace($settings['forward_form_instructions'], $token, array(
        'langcode' => $langcode,
      )),
    );
    $form['message']['email'] = array(
      '#type' => 'email',
      '#title' => $this
        ->t('Your email address'),
      '#maxlength' => 254,
      '#required' => TRUE,
    );
    $form['message']['name'] = array(
      '#type' => 'textfield',
      '#title' => $this
        ->t('Your name'),
      '#maxlength' => 128,
      '#required' => TRUE,
    );
    $form['message']['recipient'] = array(
      '#type' => 'email',
      '#title' => $this
        ->t('Send to'),
      '#maxlength' => 254,
      '#description' => $this
        ->t('Enter the email address of the recipient.'),
      '#required' => TRUE,
    );
    if ($settings['forward_form_display_page']) {
      $form['message']['page'] = array(
        '#type' => 'item',
        '#title' => $this
          ->t('You are going to email the following:'),
        '#markup' => $this->linkGenerator
          ->generate($this->entity
          ->label(), $this->entity
          ->toUrl()),
      );
    }
    if ($settings['forward_form_display_subject']) {
      $form['message']['subject'] = array(
        '#type' => 'item',
        '#title' => $this
          ->t('The message subject will be:'),
        '#markup' => $this->tokenService
          ->replace($settings['forward_email_subject'], $token, array(
          'langcode' => $langcode,
        )),
      );
    }
    if ($settings['forward_form_display_body']) {
      $form['message']['body'] = array(
        '#type' => 'item',
        '#title' => $this
          ->t('The introductory message text will be:'),
        '#markup' => $this->tokenService
          ->replace($settings['forward_email_message'], $token, array(
          'langcode' => $langcode,
        )),
      );
    }
    if ($settings['forward_personal_message']) {
      $form['message']['message'] = array(
        '#type' => 'textarea',
        '#title' => $this
          ->t('Your personal message'),
        '#default_value' => '',
        '#cols' => 50,
        '#rows' => 5,
        '#description' => $settings['forward_personal_message_filter'] ? $this
          ->t('These HTML tags are allowed in this field: @tags.', array(
          '@tags' => $settings['forward_personal_message_tags'],
        )) : t('HTML is not allowed in this field.'),
        '#required' => $settings['forward_personal_message'] == 2,
      );
    }

    // Submit button
    if ($settings['forward_interface_type'] == 'form') {

      // When using a collapsible form, move submit button into fieldset
      $form['message']['actions'] = array(
        '#type' => 'actions',
      );
      $form['message']['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => $this
          ->t('Send Message'),
        '#weight' => 100,
      );
    }
    else {

      // When using a separate form page, use actions directly
      $form['actions'] = array(
        '#type' => 'actions',
      );
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => $this
          ->t('Send Message'),
      );
    }

    // Default name and email address to logged in user
    if ($this
      ->currentUser()
      ->isAuthenticated()) {
      if ($this
        ->currentUser()
        ->hasPermission('override email address')) {
        $form['message']['email']['#default_value'] = $this
          ->currentUser()
          ->getEmail();
      }
      else {

        // User not allowed to change sender email address
        $form['message']['email']['#type'] = 'hidden';
        $form['message']['email']['#value'] = $this
          ->currentUser()
          ->getEmail();
      }
      $form['message']['name']['#default_value'] = $this
        ->currentUser()
        ->getDisplayName();
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    if (!$this
      ->currentUser()
      ->hasPermission('override flood control')) {
      $event = $this
        ->getFloodControlEventName();
      if (!$this->floodInterface
        ->isAllowed($event, $this->settings['forward_flood_control_limit'])) {
        $message = new FormattableMarkup($this->settings['forward_flood_control_error'], [
          '@number' => $this->settings['forward_flood_control_limit'],
        ]);
        $form_state
          ->setErrorByName('', $message);
      }
    }
    parent::validateForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

    // Get form values
    $entity = $form_state
      ->get('#entity');
    $recipient = $form_state
      ->getValue('recipient');

    // Use the entity language to drive translation
    $langcode = $entity
      ->language()
      ->getId();

    // Switch to anonymous user session if logged in, unless bypassing access control
    $switched = FALSE;
    if ($this
      ->currentUser()
      ->isAuthenticated() && empty($this->settings['forward_bypass_access_control'])) {
      $this->accountSwitcher
        ->switchTo(new AnonymousUserSession());
      $switched = TRUE;
    }
    try {

      // Build the message subject line
      $token = $this
        ->getToken($form_state);
      $params['subject'] = $this->tokenService
        ->replace($this->settings['forward_email_subject'], $token, array(
        'langcode' => $langcode,
      ));

      // Build the entity content
      $view_mode = '';
      $elements = array();
      if ($entity
        ->access('view')) {
        $view_builder = $this->entityTypeManager
          ->getViewBuilder($entity
          ->getEntityTypeId());
        $view_mode = 'forward';
        if ($this
          ->isValidDisplay($entity, $view_mode)) {
          $elements = $view_builder
            ->view($entity, $view_mode, $langcode);
        }
        if (empty($elements)) {
          $view_mode = 'teaser';
          if ($this
            ->isValidDisplay($entity, $view_mode)) {
            $elements = $view_builder
              ->view($entity, $view_mode, $langcode);
          }
        }
        if (empty($elements)) {
          $view_mode = 'full';
          $elements = $view_builder
            ->view($entity, $view_mode, $langcode);
        }
      }
      $elements['#forward_build'] = TRUE;

      // prevent recursion
      $content = $this->renderer
        ->render($elements);

      // Build the header line
      $header = [
        '#markup' => $this->tokenService
          ->replace($this->settings['forward_email_message'], $token, array(
          'langcode' => $langcode,
        )),
      ];

      // Build the personal message if present
      $message = '';
      if ($this->settings['forward_personal_message']) {
        if ($this->settings['forward_personal_message_filter']) {

          // HTML allowed in personal message, so filter out anything but the allowed tags
          $raw_values = $form_state
            ->getUserInput();
          $allowed_tags = explode(',', $this->settings['forward_personal_message_tags']);
          $message = !empty($raw_values['message']) ? Xss::filter($raw_values['message'], $allowed_tags) : '';
          $message = [
            '#markup' => nl2br($message),
          ];
        }
        else {

          // HTML not allowed in personal message, so use the sanitized version converted to plain text
          $message = [
            '#plain_text' => nl2br($form_state
              ->getValue('message')),
          ];
        }
      }

      // Build the email body
      $render_array = array(
        '#theme' => 'forward',
        '#email' => $form_state
          ->getValue('email'),
        '#header' => $header,
        '#message' => $message,
        '#settings' => $this->settings,
        '#entity' => $entity,
        '#content' => $content,
        '#view_mode' => $view_mode,
      );

      // Allow modules to alter the render array for the message
      $this->moduleHandler
        ->alter('forward_mail_pre_render', $render_array, $form_state);

      // Render the message
      $params['body'] = $this->renderer
        ->render($render_array);

      // Apply filters such as Pathologic for link correction
      if ($this->settings['forward_filter_format']) {

        // This filter was setup by the Forward administrator for this purpose only, whose permission to run the filter was checked at that time
        // Therefore, no need to check filter access again here
        $params['body'] = check_markup($params['body'], $this->settings['forward_filter_format'], $langcode);
      }

      // Allow modules to alter the final message body
      $this->moduleHandler
        ->alter('forward_mail_post_render', $params['body'], $form_state);
    } catch (Exception $e) {
      if ($switched) {
        $this->accountSwitcher
          ->switchBack();
        $switched = FALSE;
      }
      $this
        ->logger('forward')
        ->error($e
        ->getMessage());
    }

    // Switch back to logged in user if necessary
    if ($switched) {
      $this->accountSwitcher
        ->switchBack();
    }

    // Build the from email address and Reply-To
    $from = $this->settings['forward_email_from_address'];
    if (empty($from)) {
      $from = $this
        ->config('system.site')
        ->get('mail');
    }
    if (empty($from)) {
      $site_mail = ini_get('sendmail_from');
    }
    $params['headers']['Reply-To'] = trim(Unicode::mimeHeaderEncode($form_state
      ->getValue('name')) . ' <' . $form_state
      ->getValue('email') . '>');

    // Prepare for Event dispatch
    $account = $this->entityTypeManager
      ->getStorage('user')
      ->load($this
      ->currentUser()
      ->id());

    // Event dispatch - before forwarding
    $event = new EntityPreforwardEvent($account, $entity, [
      'account' => $account,
      'entity' => $entity,
    ]);
    $this->eventDispatcher
      ->dispatch(EntityPreforwardEvent::EVENT_NAME, $event);

    // Send the email to the recipient
    $key = 'send_entity';
    $this->mailer
      ->mail('forward', $key, $recipient, $langcode, $params, $from);

    // Log this for tracking purposes
    $this
      ->logEvent($entity);

    // Register event for flood control
    $event = $this
      ->getFloodControlEventName();
    $this->floodInterface
      ->register($event);

    // Event dispatch - after forwarding
    $event = new EntityForwardEvent($account, $entity, [
      'account' => $account,
      'entity' => $entity,
    ]);
    $this->eventDispatcher
      ->dispatch(EntityForwardEvent::EVENT_NAME, $event);

    // Allow modules to post process the forward
    $this->moduleHandler
      ->invokeAll('forward_entity', array(
      $account,
      $entity,
      $form_state,
    ));

    // Display a confirmation message
    $message = $this->tokenService
      ->replace($this->settings['forward_form_confirmation'], $token, array(
      'langcode' => $langcode,
    ));
    if ($message) {
      drupal_set_message($message);
    }

    // Redirect back to entity page unless a redirect is already set
    if ($this->settings['forward_interface_type'] == 'link') {
      if (!$form_state
        ->getRedirect()) {
        $form_state
          ->setRedirectUrl($entity
          ->toUrl());
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormBase::$configFactory protected property The config factory. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 1
FormBase::container private function Returns the service container.
FormBase::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create 87
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
ForwardForm::$accountSwitcher protected property The account switcher service.
ForwardForm::$database protected property The database connection.
ForwardForm::$entity protected property The entity being forwarded.
ForwardForm::$entityTypeManager protected property The entity type manager.
ForwardForm::$eventDispatcher protected property The event dispatcher service.
ForwardForm::$floodInterface protected property The flood interface.
ForwardForm::$linkGenerator protected property The link generation service. Overrides LinkGeneratorTrait::$linkGenerator
ForwardForm::$mailer protected property The mail service.
ForwardForm::$moduleHandler protected property The module handler service.
ForwardForm::$renderer protected property The render service.
ForwardForm::$requestStack protected property The request stack. Overrides FormBase::$requestStack
ForwardForm::$settings protected property The settings for this form.
ForwardForm::$tokenService protected property The token service.
ForwardForm::buildForm public function Form constructor. Overrides FormInterface::buildForm
ForwardForm::cleanString private function Clean a string
ForwardForm::getBaseFormId public function Returns a string identifying the base form. Overrides BaseFormIdInterface::getBaseFormId
ForwardForm::getEditableConfigNames protected function
ForwardForm::getFloodControlEventName private function Get the event name used for Flood control
ForwardForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
ForwardForm::getToken private function Get a token
ForwardForm::injectServices public function Inject services.
ForwardForm::isValidDisplay private function Determine if a given display is valid for an entity
ForwardForm::logEvent private function Logging
ForwardForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
ForwardForm::validateForm public function Form validation handler. Overrides FormBase::validateForm
ForwardForm::__construct public function Constructs a Forward Form.
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.