You are here

class PathChecker in Optimizely 8.0

Same name and namespace in other branches
  1. 8 src/PathChecker.php \Drupal\optimizely\PathChecker

Provides static methods to check path validity, etc.

Hierarchy

Expanded class hierarchy of PathChecker

File

src/PathChecker.php, line 14
Contains \Drupal\optimizely\src\PathChecker

Namespace

Drupal\optimizely
View source
class PathChecker {
  use LookupPath;

  /**
   * validatePaths()
   *
   * Validate the target paths.
   *
   * @parm $target_paths
   *   An array of the paths to validate.
   * @parm $include
   *   Boolean, TRUE if the paths are included or FALSE for exclude paths
   *
   * @return
   *   Boolean of TRUE if the paths are valid or a string of the path that failed.
   */
  public static function validatePaths($project_paths) {

    // Validate entered paths to confirm the paths exist on the website
    foreach ($project_paths as $path) {

      // Check for sitewide wildcard
      if (strpos($path, '*') === 0) {
        if (count($project_paths) == 1) {
          return TRUE;
        }
        else {
          return $path;
        }
      }
      elseif (strpos($path, '*') !== FALSE) {
        $project_wildpath = substr($path, 0, -2);
        if (\Drupal::pathValidator()
          ->isValid($project_wildpath) == FALSE) {

          // Look for entries in url_alias
          $query = db_query("SELECT * FROM {url_alias} WHERE\n            source LIKE :project_wildpath OR alias LIKE :project_wildpath", array(
            ':project_wildpath' => $project_wildpath . '%',
          ));
          $results = $query
            ->fetchCol(0);
          $project_wildpath_match = count($results);

          // No matches found for wildcard path
          if (!$project_wildpath_match) {
            return $path;
          }
        }
      }
      elseif (strpos($path, '?') !== FALSE) {

        // Look for entries in menu_router
        $project_parmpath = substr($path, 0, strpos($path, '?'));

        // Look for entry in url_alias table
        if (self::lookupPathAlias($path) === FALSE && self::lookupSystemPath($path) === FALSE && \Drupal::pathValidator()
          ->isValid($project_parmpath) == FALSE) {
          return $path;
        }
      }
      elseif (\Drupal::pathValidator()
        ->isValid($path) == FALSE) {

        // Look for entry in url_alias table
        if (self::lookupPathAlias($path) === FALSE && self::lookupSystemPath($path) === FALSE) {
          return $path;
        }
      }
    }
    return TRUE;
  }

  /*
   * Compare target path against the project paths to confirm they're unique
   *
   * @parm
   *   $target_paths - the paths entered for a new project entry, OR
   *   the paths of an existing project entry that has been enabled.
   * @parm
   *   $target_oid = NULL : the oid of the project entry that has been enabled
   *
   * @return
   *   $target_path: the path that is a duplicate that must be addressed to
   *   enable or create the new project entry, or TRUE if unique paths.
   */
  public static function uniquePaths($target_paths, $target_oid = NULL) {

    // Look up alternative paths
    $target_paths = self::collectAlias($target_paths);

    // Look for duplicate paths in submitted $target_paths
    $duplicate_target_path = self::duplicateCheck($target_paths);

    // Look for duplicate paths within target paths
    if (!$duplicate_target_path) {

      // Collect all of the existing project paths that are enabled,
      $query = db_select('optimizely', 'o', array(
        'target' => 'slave',
      ))
        ->fields('o', array(
        'oid',
        'project_title',
        'path',
      ))
        ->condition('o.enabled', 1, '=');

      // Add target_oid to query when it's an update, $target_oid is defined
      if ($target_oid != NULL) {
        $query = $query
          ->condition('o.oid', $target_oid, '<>');
      }
      $projects = $query
        ->execute();

      // No other enabled projects
      if ($query
        ->countQuery()
        ->execute()
        ->fetchField() == 0) {
        return array(
          TRUE,
          NULL,
        );
      }
      $all_project_paths = array();

      // Build array of all the project entry paths
      foreach ($projects as $project) {

        // Collect all of the path values and merge into collective array
        $project_paths = unserialize($project->path);
        $all_project_paths = array_merge($all_project_paths, $project_paths);
      }

      // Add any additional aliases to catch all match possiblities
      $all_project_paths = self::collectAlias($all_project_paths);

      // Convert array into string for drupal_match_path()
      $all_project_paths_string = implode("\n", $all_project_paths);

      // Check all of the paths for all of the active project entries to make sure
      // the paths are unique
      foreach ($target_paths as $target_path) {

        // "*" found in path
        if (strpos($target_path, '*') !== FALSE) {

          // Look for wild card match if not sitewide
          if (strpos($target_path, '*') !== 0) {
            $target_path = substr($target_path, 0, -2);

            // Look for duplicate path due to wild card
            foreach ($all_project_paths as $all_project_path) {

              //
              if (strpos($all_project_path, $target_path) === 0 && $all_project_path != $target_path) {
                return array(
                  $project->project_title,
                  $target_path,
                );
              }
            }
          }
          elseif (strpos($target_path, '*') === 0 && (count($target_paths) > 1 || count($all_project_paths) > 0)) {
            return array(
              $project->project_title,
              $target_path,
            );
          }

          // Look for sitewide wild card in target project paths
          if (in_array('*', $all_project_paths)) {
            return array(
              $project->project_title,
              $target_path,
            );
          }
        }
        elseif (strpos($target_path, '?') !== FALSE) {
          $target_path = substr($target_path, 0, strpos($target_path, '?'));
        }

        // Look for duplicates
        if (\Drupal::service('path.matcher')
          ->matchPath($target_path, $all_project_paths_string)) {
          return array(
            $project->project_title,
            $target_path,
          );
        }
      }
      return array(
        TRUE,
        NULL,
      );
    }
    else {
      return array(
        NULL,
        $duplicate_target_path,
      );
    }
  }

  /*
   * Lookup all alternatives to the group of paths - alias, <front>
   *
   * @parm
   *   $paths - a set of paths to be reviewed for alternatives
   *
   * @return
   *   $paths - an updated list of paths that include the additional source and alias values.
   */
  private static function collectAlias($paths) {

    // Add alternative values - alias, source, <front> to ensure matches
    // also check different possibilities
    foreach ($paths as $path_count => $path) {

      // Remove parameters
      if (strpos($path, '?') !== FALSE) {
        $path = substr($path, 0, strpos($path, '?'));
        $paths[$path_count] = $path;
      }
      !self::lookupPathAlias($path) ?: ($paths[] = self::lookupPathAlias($path));
      !self::lookupSystemPath($path) ?: ($paths[] = self::lookupSystemPath($path));

      // Collect all the possible values to match <front>
      if ($path == '<front>') {
        $frontpage = \Drupal::config('system.site')
          ->get('page.front');
        if ($frontpage) {
          $paths[] = $frontpage;
          $paths[] = self::lookupPathAlias($frontpage);
        }
      }
    }
    return $paths;
  }

  /*
   * Compare paths within passed array to ensure each item resolves to a unique entry
   *
   * @parm
   *   $paths - a set of paths to be reviewed for uniqueness
   *
   * @return
   *   FALSE if no duplicates found otherwaise the dusplicate path is returned.
   */
  private static function duplicateCheck($paths) {
    $unreviewed_paths = $paths;

    // Check all of the paths
    foreach ($paths as $path) {

      // Remove path that's being processed from the front of the list
      array_shift($unreviewed_paths);

      // "*" found in path
      if (strpos($path, '*') !== FALSE) {

        // Look for wild card match that's not sitewide (position not zero (0))
        if (strpos($path, '*') !== 0) {
          $path = substr($path, 0, -2);
          foreach ($unreviewed_paths as $unreviewed_path) {
            if (strpos($unreviewed_path, $path) !== FALSE) {
              return $path . '/*';
            }
          }
        }
        elseif (strpos($path, '*') === 0 && count($paths) > 1) {
          return $path;
        }
      }
      elseif (in_array($path, $unreviewed_paths)) {
        return $path;
      }
    }
    return FALSE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
LookupPath::checkPath static function Ensure that $path starts with a forward slash because the alias_manager requires it.
LookupPath::lookupPathAlias static function Helper function to lookup a path alias, given a path. This function acts as an adapter and passes back a return value like those of drupal_lookup_path(), which has been removed as of Drupal 8.
LookupPath::lookupSystemPath static function Helper function to lookup a system path, given a path alias. This function acts as an adapter and passes back a return value like those of drupal_lookup_path(), which has been removed as of Drupal 8.
PathChecker::collectAlias private static function
PathChecker::duplicateCheck private static function
PathChecker::uniquePaths public static function
PathChecker::validatePaths public static function validatePaths()