Commit c9fd0939 authored by Binny Thomas's avatar Binny Thomas Committed by Binny Thomas
Browse files

Issue #3310784 by binnythomas: Port the key Affiliate tracking page callback...

Issue #3310784 by binnythomas: Port the key Affiliate tracking page callback to the Drupal 9 Route Controller setup
parent 8f9488bf
Loading
Loading
Loading
Loading
+73 −0
Original line number Diff line number Diff line
@@ -7,6 +7,10 @@ use Drupal\Core\Render\Markup;
use Drupal\core\Database;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Component\Utility\Xss;
use Drupal\Component\Utility\UrlHelper;


/**
 * Affiliate Overview page class.
@@ -74,4 +78,73 @@ class UberAffiliate extends ControllerBase {
    ];

  }

  /**
   * The primary tracking of the affiliate and the main affiliate link.
   * @todo
   *   Have this function checked by security team if possible, or if not, get a second opinion just to be sure.
   */
  public function affiliate_page($aff_id, $dest_path, $tracker_id) {
    $allow_all_paths = \Drupal::state()->get('affiliate_module_allow_all_paths', 0);
    $allow_all_node_types = \Drupal::state()->get('affiliate_module_allow_all_node_types', 0);





    $affid =  (int) Xss::filter($aff_id);
    $path_given = $dest_path;
    $tracker = (int) Xss::filter($tracker_id);



    // Note to self: ask a security guru about this.
    $path_arg = UrlHelper::stripDangerousProtocols(implode('/', explode('|', rawurldecode($path_given))));

    $verify_node_type = FALSE;
    if (!$allow_all_node_types) {
      $verify_node_type = TRUE;
    }
    if ($allow_all_paths) {
      $verify_node_type = FALSE;
    }

    if (!isset($tracker) || empty($tracker)) {
      $tracker = 0;
    }
    if (!isset($affid) || empty($affid)) {
      $affid = 1;
    }

    // Send invalid clicks to the front page if no path argument is supplied.
    if (!isset($path_arg) || empty($path_arg)) {
      $path = base_path();
    }
    else {
      $path = $path_arg;
    }
    // Path aliases will fail validation... Convert to normal path before validating.
    $path_normal = \Drupal::service('path_alias.manager')->getPathByAlias($path);

    // This seems like it could be written better...?
    if (affiliate_validate_click($affid, $path_normal, $verify_node_type)) {
      $campaign_id = affiliate_get_campaign_id($path_normal);
      affiliate_add_click($affid, $campaign_id);
    }
    $destination_is_valid = affiliate_valid_destination($path_normal);

    // Empty will simply take us to the front page, in case the path doesn't validate.
    $destination_actual = '';
    if ($destination_is_valid) {
      $destination_actual = drupal_get_path_alias($path_normal);
    }

    // Unnecessary check_url()? Better safe than sorry...
    $destination_actual = check_url($destination_actual);

    // At minimum, if all validations fail, we'll be taken to the front page. If the path
    // given is valid though, we'll be taken to that path either way, regardless of whether
    // the affiliate was credited with a valid click-thru.
    return new RedirectResponse(\Drupal\Core\Url::fromRoute($destination_actual)->toString());
  }
}
+0 −1
Original line number Diff line number Diff line
@@ -100,7 +100,6 @@ class AdminContentForm extends ConfigFormBase {
  }



  /**
   * Required by FormBase.
   */
+38 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\uber_affiliate\Routing;

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

/**
 * Class EntityOverview
 *
 * @package Drupal\uber_affiliate\Routing
 */
class AffiliateRoute {

  /**
   * Dynamically generate the routes for the entity details.
   *
   * @return \Symfony\Component\Routing\RouteCollection
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function routes() {

    $affiliate_menu_path = \Drupal::state()->get('affiliate_module_affiliate_menu_path', 'affiliate');
    $routes = [];
    $routes['affiliate'] = new Route(
      $affiliate_menu_path . '/' .   '{aff_id}' . '/' . '{dest_path}' . '/' . '{tracker_id}',
      [
        '_controller' => 'Drupal\uber_affiliate\Controller\UberAffiliate::affiliate_page',
      ],
      [
        '_permission'  => 'track affiliate clicks for this role',
      ],
      );


    return $routes;
  }
}
+8 −64
Original line number Diff line number Diff line
<?php

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Url;


/**
 * Set the time of the current "clicks" update so the next time cron runs, only clicks newer than this
 * time will be added to each affiliate's running total.
@@ -240,7 +244,7 @@ function affiliate_fetch_all() {
 */
function affiliate_validate_click($affid, $dest, $verify_node_type = TRUE) {
  $affid = (int) $affid;
  $dest = check_url($dest);
  $dest = UrlHelper::stripDangerousProtocols($dest);
  $node_path_pattern = '<^(node/)([0-9]+)$>';
  $is_node_path = preg_match($node_path_pattern, $dest, $node_path_matches);
  $nid = 0;
@@ -292,13 +296,13 @@ function affiliate_validate_click($affid, $dest, $verify_node_type = TRUE) {
 *   TRUE if $dest is a valid affiliate path, otherwise FALSE.
 */
function affiliate_valid_destination($dest) {
  if (!drupal_valid_path($dest)) {
  if (!\Drupal::service('path.validator')->isValid($dest)) {
    return FALSE;
  }
  if (url_is_external($dest)) {
  if (UrlHelper::isExternal($dest)) {
    return FALSE;
  }
  if (path_is_admin($dest)) {
  if (\Drupal::service('router.admin_context')->isAdminRoute($url_object)) {
    return FALSE;
  }
  return TRUE;
@@ -563,67 +567,7 @@ function _affiliate_check_timer() {
  return (bool) \Drupal::database()->query("SELECT COUNT(*) FROM {affiliate_clicks} WHERE ip = :ip AND click_time > :limit", array(":ip" => $ip, ":limit" => $limit))->fetchField();
}

/**
 * @todo
 *   Have this function checked by security team if possible, or if not, get a second opinion just to be sure.
 */
function affiliate_page() {
  $allow_all_paths = \Drupal::state()->get('affiliate_module_allow_all_paths', 0);
  $allow_all_node_types = \Drupal::state()->get('affiliate_module_allow_all_node_types', 0);

  $affid = (int) filter_xss(arg(1));
  $path_given = arg(2);
  $tracker = (int) filter_xss(arg(3));

  // Note to self: ask a security guru about this.
  $path_arg = check_url(implode('/', explode('|', rawurldecode($path_given))));

  $verify_node_type = FALSE;
  if (!$allow_all_node_types) {
    $verify_node_type = TRUE;
  }
  if ($allow_all_paths) {
    $verify_node_type = FALSE;
  }

  if (!isset($tracker) || empty($tracker)) {
    $tracker = 0;
  }
  if (!isset($affid) || empty($affid)) {
    $affid = 1;
  }

  // Send invalid clicks to the front page if no path argument is supplied.
  if (!isset($path_arg) || empty($path_arg)) {
    $path = base_path();
  }
  else {
    $path = $path_arg;
  }
  // Path aliases will fail validation... Convert to normal path before validating.
  $path_normal = drupal_get_normal_path($path);

  // This seems like it could be written better...?
  if (affiliate_validate_click($affid, $path_normal, $verify_node_type)) {
    $campaign_id = affiliate_get_campaign_id($path_normal);
    affiliate_add_click($affid, $campaign_id);
  }
  $destination_is_valid = affiliate_valid_destination($path_normal);

  // Empty will simply take us to the front page, in case the path doesn't validate.
  $destination_actual = '';
  if ($destination_is_valid) {
    $destination_actual = drupal_get_path_alias($path_normal);
  }

  // Unnecessary check_url()? Better safe than sorry...
  $destination_actual = check_url($destination_actual);

  // At minimum, if all validations fail, we'll be taken to the front page. If the path
  // given is valid though, we'll be taken to that path either way, regardless of whether
  // the affiliate was credited with a valid click-thru.
  drupal_goto($destination_actual);
}

function affiliate_user_page($account) {
  global $user;
+3 −0
Original line number Diff line number Diff line
@@ -48,3 +48,6 @@ uber_affiliate.affiliatemanagement.payouts:
    _title: 'Payout Form'
  requirements:
    _permission: 'administer affiliate settings'

route_callbacks:
  - '\Drupal\uber_affiliate\Routing\AffiliateRoute::routes'