GetDKAN/dkan

View on GitHub
modules/frontend/src/Routing/RouteProvider.php

Summary

Maintainability
A
45 mins
Test Coverage
A
98%
<?php

namespace Drupal\frontend\Routing;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\Query\QueryFactoryInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

/**
 * DKAN Frontend route provider.
 */
class RouteProvider {

  /**
   * App root directory for react data catalog app.
   *
   * @var string
   */
  private $appRoot;

  /**
   * Query factory service.
   *
   * @var \Drupal\Core\Entity\Query\QueryFactoryInterface
   */
  private QueryFactoryInterface $entityQuery;

  /**
   * Build folder config.
   *
   * @var string
   */
  private $buildFolder;

  /**
   * Frontend path config.
   *
   * @var string
   */
  private $frontendPath;

  /**
   * Routes config.
   *
   * @var array
   */
  private $routes;

  /**
   * Constructor.
   */
  public function __construct(
    string $appRoot,
    QueryFactoryInterface $entityQuery,
    ConfigFactoryInterface $configFactory
  ) {
    $this->appRoot = $appRoot;
    $this->entityQuery = $entityQuery;
    $this->buildFolder = $configFactory->get('frontend.config')->get('build_folder');
    $this->frontendPath = $configFactory->get('frontend.config')->get('frontend_path');
    $this->routes = $configFactory->get('frontend.config')->get('routes');
  }

  /**
   * Routes.
   */
  public function routes() {
    $routes = new RouteCollection();

    $package_json_path = $this->appRoot . $this->frontendPath . "/package.json";
    if (is_file($package_json_path)) {
      $package_json = file_get_contents($package_json_path);
      $decode_package = json_decode($package_json, TRUE);
    }
    if (isset($decode_package["dependencies"]["gatsby"])) {
      $this->addStaticPages($routes);
    }
    else {
      $this->addIndexPage($routes);
    }
    $routes->addRequirements(['_access' => 'TRUE']);

    return $routes;
  }

  /**
   * Public.
   */
  public function getNameFromPath($path) {
    $base = $this->appRoot . $this->frontendPath . $this->buildFolder;
    $sub = str_replace($base, "", $path);
    return str_replace("/", "__", $sub);
  }

  /**
   * Private.
   */
  private function expandDirectories($base_dir) {
    $directories = [];

    if (!file_exists($base_dir)) {
      return $directories;
    }

    foreach (scandir($base_dir) as $file) {
      if ($file == '.' || $file == '..') {
        continue;
      }
      $dir = $base_dir . DIRECTORY_SEPARATOR . $file;
      if (is_dir($dir)) {
        $directories[] = $dir;
        $directories = array_merge($directories, $this->expandDirectories($dir));
      }
    }
    return $directories;
  }

  /**
   * Route Helper.
   *
   * @param string $path
   *   Path.
   * @param string $name
   *   Name.
   *
   * @return \Symfony\Component\Routing\Route
   *   Route.
   */
  private function routeHelper(string $path, string $name) : Route {
    $route = new Route(
          "/$path",
          [
            '_controller' => '\Drupal\frontend\Controller\Page::page',
            'name' => $name,
          ]
      );
    $route->setMethods(['GET']);
    return $route;
  }

  /**
   * Private. Each route returns its own JS file.
   */
  private function addStaticPages(RouteCollection $routes) {
    $base = $this->appRoot . $this->frontendPath . $this->buildFolder;
    $possible_pages = $this->expandDirectories($base);
    foreach ($possible_pages as $possible_page) {
      if (file_exists($possible_page . "/index.html")) {
        $name = $this->getNameFromPath($possible_page);
        $path = str_replace($base, "", $possible_page);
        $routes->add($name, $this->routeHelper($path, $name));
      }
    }

    $route = new Route(
      "/home",
      [
        '_controller' => '\Drupal\frontend\Controller\Page::page',
        'name' => 'home',
      ]
    );
    $route->setMethods(['GET']);
    $routes->add('home', $route);
  }

  /**
   * Private. All routes return root JS file.
   */
  private function addIndexPage(RouteCollection $routes) {
    $config_routes = $this->routes ?? [];
    foreach ($config_routes as $config_route) {
      $possible_page = explode(",", $config_route);
      $routes->add($possible_page[0], $this->routeHelper($possible_page[1], "home"));
    }

  }

}