You are here

InfoForm.php in Advanced CSS/JS Aggregation 8.2

Same filename and directory in other branches
  1. 8.4 src/Form/InfoForm.php
  2. 8.3 src/Form/InfoForm.php

Namespace

Drupal\advagg\Form

File

src/Form/InfoForm.php
View source
<?php

namespace Drupal\advagg\Form;

use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\Translator\TranslatorInterface;
use Drupal\Core\Theme\Registry;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * View AdvAgg information for this site.
 */
class InfoForm extends ConfigFormBase {

  /**
   * The theme registry service.
   *
   * @var \Drupal\Core\Theme\Registry
   */
  protected $themeRegistry;

  /**
   * The AdvAgg file status state information storage service.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected $advaggFiles;

  /**
   * The AdvAgg aggregates state information storage service.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected $advaggAggregates;

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

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * The string translation service.
   *
   * @var \Drupal\Core\StringTranslation\Translator\TranslatorInterface
   */
  protected $translation;

  /**
   * Constructs a SettingsForm object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The factory for configuration objects.
   * @param \Drupal\Core\Theme\Registry $theme_registry
   *   The theme registry service.
   * @param \Drupal\Core\State\StateInterface $advagg_files
   *   The AdvAgg file status state information storage service.
   * @param \Drupal\Core\State\StateInterface $advagg_aggregates
   *   The AdvAgg aggregate state information storage service.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The Date formatter service.
   * @param \Drupal\Core\StringTranslation\Translator\TranslatorInterface $string_translation
   *   The string translation service.
   */
  public function __construct(ConfigFactoryInterface $config_factory, Registry $theme_registry, StateInterface $advagg_files, StateInterface $advagg_aggregates, RequestStack $request_stack, DateFormatterInterface $date_formatter, TranslatorInterface $string_translation) {
    parent::__construct($config_factory);
    $this->themeRegistry = $theme_registry;
    $this->advaggFiles = $advagg_files;
    $this->advaggAggregates = $advagg_aggregates;
    $this->requestStack = $request_stack;
    $this->dateFormatter = $date_formatter;
    $this->translation = $string_translation;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('config.factory'), $container
      ->get('theme.registry'), $container
      ->get('state.advagg.files'), $container
      ->get('state.advagg.aggregates'), $container
      ->get('request_stack'), $container
      ->get('date.formatter'), $container
      ->get('string_translation'));
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'advagg_info';
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = [];
    $form['tip'] = [
      '#markup' => '<p>' . $this
        ->t('This page provides debugging information. There are no configuration options here.') . '</p>',
    ];

    // Get all hooks and variables.
    $core_hooks = $this->themeRegistry
      ->get();
    $advagg_hooks = advagg_hooks_implemented();

    // Output html preprocess functions hooks.
    $form['theme_info'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Hook Theme Info'),
    ];
    $data = implode("\n", $core_hooks['html']['preprocess functions']);
    $form['theme_info']['advagg_theme_info'] = [
      '#markup' => '<p>preprocess functions on html.</p><pre>' . $data . '</pre>',
    ];
    $file_data = $this->advaggFiles
      ->getAll();

    // Get all parent css and js files.
    $types = [
      'css',
      'js',
    ];
    foreach ($types as $type) {
      $form[$type] = [
        '#type' => 'details',
        '#title' => $this
          ->t('@type files', [
          '@type' => Unicode::strtoupper($type),
        ]),
      ];
    }
    foreach ($file_data as $name => $info) {
      if (!in_array($info['fileext'], $types)) {
        continue;
      }
      $form[$info['fileext']][$info['filename_hash']] = [
        '#markup' => '<details><summary>' . $this->translation
          ->formatPlural($info['changes'], 'changed 1 time - %file<br />', 'changed %changes times - %file<br />', [
          '%changes' => $info['changes'],
          '%file' => $name,
        ]) . '</summary><div class="details-wrapper"><pre>' . print_r($info, TRUE) . '</pre></div></details>',
      ];
    }

    // Display as module -> hook instead of hook -> module.
    ksort($advagg_hooks);
    $module_hooks = [];
    foreach ($advagg_hooks as $hook => $values) {
      if (!empty($values)) {
        foreach ($values as $module_name) {
          if (!isset($module_hooks[$module_name])) {
            $module_hooks[$module_name] = [];
          }
          $module_hooks[$module_name][] = $hook;
        }
      }
      else {
        $module_hooks['not in use'][] = $hook;
      }
    }
    ksort($module_hooks);
    $form['modules_implementing_advagg'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Modules implementing aggregate hooks'),
    ];
    $form['hooks_implemented'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('AdvAgg CSS/JS hooks implemented by modules'),
    ];

    // Output all advagg hooks implemented.
    foreach ($module_hooks as $hook => $values) {
      if (empty($values)) {
        $form['modules_implementing_advagg'][$hook] = [
          '#markup' => '<div><strong>' . $hook . ':</strong> 0</div>',
        ];
      }
      else {
        $form['modules_implementing_advagg'][$hook] = [
          '#markup' => '<div><strong>' . $hook . ':</strong> ' . count($values) . $this
            ->formatList($values) . '</div>',
        ];
      }
    }

    // Output all advagg hooks implemented.
    foreach ($advagg_hooks as $hook => $values) {
      if (empty($values)) {
        $form['hooks_implemented'][$hook] = [
          '#markup' => '<div><strong>' . $hook . ':</strong> 0</div>',
        ];
      }
      else {
        $form['hooks_implemented'][$hook] = [
          '#markup' => '<div><strong>' . $hook . ':</strong> ' . count($values) . $this
            ->formatList($values) . '</div>',
        ];
      }
    }

    // Output what is used inside of advagg_get_current_hooks_hash().
    $form['hooks_variables_hash'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Hooks And Variables Used In Hash'),
    ];
    $form['hooks_variables_hash']['description'] = [
      '#markup' => $this
        ->t('Current Value: %value. Below is the listing of variables and hooks used to generate the 3rd hash of an aggregates filename.', [
        '%value' => advagg_get_current_hooks_hash(),
      ]),
    ];
    $form['hooks_variables_hash']['output'] = [
      // @ignore production_php
      '#markup' => '<pre>' . print_r(advagg_current_hooks_hash_array(), TRUE) . '</pre>',
    ];

    // Get info about a file.
    $form['get_info_about_agg'] = [
      '#type' => 'details',
      '#open' => TRUE,
      '#title' => $this
        ->t('Get detailed info about an aggregate file'),
    ];
    $form['get_info_about_agg']['filename'] = [
      '#type' => 'textfield',
      '#size' => 170,
      '#maxlength' => 256,
      '#default_value' => '',
      '#title' => $this
        ->t('Filename'),
    ];
    $form['get_info_about_agg']['submit'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Lookup Details'),
      '#submit' => [
        '::getFileInfoSubmit',
      ],
      '#validate' => [
        '::getFileInfoValidate',
      ],
      '#ajax' => [
        'callback' => '::getFileInfoAjax',
        'wrapper' => 'advagg-file-info-ajax',
        'effect' => 'fade',
      ],
    ];
    $form['get_info_about_agg']['tip'] = [
      '#markup' => '<p>' . $this
        ->t('Takes input like "@css_file" or a full aggregate name like "@advagg_js"', [
        '@css_file' => $this->advaggFiles
          ->getRandomKey(),
        '@advagg_js' => $this->advaggAggregates
          ->getRandom()['uid'],
      ]) . '</p>',
    ];
    $form['get_info_about_agg']['wrapper'] = [
      '#prefix' => "<div id='advagg-file-info-ajax'>",
      '#suffix' => "</div>",
    ];
    $form = parent::buildForm($form, $form_state);
    unset($form['actions']);
    return $form;
  }

  /**
   * Format an indented list from array.
   *
   * @param array $list
   *   The array to convert to a string.
   * @param int $depth
   *   (optional) Depth multiplier for indentation.
   *
   * @return string
   *   The imploded and spaced array.
   */
  private function formatList(array $list, $depth = 1) {
    $spacer = '<br />' . str_repeat('&nbsp;', 2 * $depth);
    $output = $spacer . Xss::filter(implode($spacer, $list), [
      'br',
    ]);
    return $output;
  }

  /**
   * Display file info in a drupal message.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function getFileInfoSubmit(array &$form, FormStateInterface $form_state) {
    $info = $this
      ->getFileInfo($form_state
      ->getValue('filename'));
    $output = '<pre>' . print_r($info, TRUE) . '</pre>';
    if (!$this
      ->isAjax()) {
      drupal_set_message($output);
    }
  }

  /**
   * Display file info via ajax callback.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function getFileInfoAjax(array &$form, FormStateInterface $form_state) {
    $element = $form['get_info_about_agg']['wrapper'];
    if ($form_state
      ->hasAnyErrors()) {
      return $element;
    }
    $info = $this
      ->getFileInfo($form_state
      ->getValue('filename'));
    if (empty($info)) {
      $form_state
        ->setErrorByName('filename', $this
        ->t('Please input a valid aggregate filename.'));
      return $element;
    }
    else {
      $element['#markup'] = '<pre>' . print_r($info, TRUE) . '</pre>';
      return $element;
    }
  }

  /**
   * Verify that the filename is correct.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function getFileInfoValidate(array &$form, FormStateInterface $form_state) {
    if (empty($form_state
      ->getValue('filename'))) {
      $form_state
        ->setErrorByName('filename', $this
        ->t('Please input an aggregate filename.'));
    }
  }

  /**
   * Get detailed info about the given filename.
   *
   * @param string $filename
   *   Name of file to lookup.
   *
   * @return array
   *   Returns an array of detailed info about this file.
   */
  private function getFileInfo($filename) {

    // Strip quotes and trim.
    $filename = trim(str_replace([
      '"',
      "'",
    ], '', $filename));
    if (substr_compare($filename, 'css_', 0) > 0 || substr_compare($filename, 'js_', 0) > 0) {
      $results = array_column($this->advaggAggregates
        ->getAll(), NULL, 'uid');
      if (isset($results[$filename])) {
        return $results[$filename];
      }
      else {
        return "Aggregate name unrecognized, confirm spelling, otherwise likely a very old aggregate that has been expunged.";
      }
    }
    elseif ($data = $this->advaggFiles
      ->get($filename)) {
      $data['File modification date'] = $this->dateFormatter
        ->format($data['mtime'], 'html_datetime');
      $data['Information last update'] = $this->dateFormatter
        ->format($data['updated'], 'html_datetime');
      return $data;
    }
    else {
      return "File not found and AdvAgg has no record of it. Confirm spelling of the path.";
    }
  }

  /**
   * Checks if the form was submitted by AJAX.
   *
   * @return bool
   *   TRUE if the form was submitted via AJAX, otherwise FALSE.
   */
  private function isAjax() {
    $request = $this->requestStack
      ->getCurrentRequest();
    if ($request->query
      ->has(FormBuilderInterface::AJAX_FORM_REQUEST)) {
      return TRUE;
    }
    return FALSE;
  }

}

Classes

Namesort descending Description
InfoForm View AdvAgg information for this site.