You are here

class CssW3Form in Advanced CSS/JS Aggregation 8.2

Same name and namespace in other branches
  1. 8.4 advagg_validator/src/Form/CssW3Form.php \Drupal\advagg_validator\Form\CssW3Form
  2. 8.3 advagg_validator/src/Form/CssW3Form.php \Drupal\advagg_validator\Form\CssW3Form

Configure form for W3C validation of CSS files.

Hierarchy

Expanded class hierarchy of CssW3Form

1 string reference to 'CssW3Form'
advagg_validator.routing.yml in advagg_validator/advagg_validator.routing.yml
advagg_validator/advagg_validator.routing.yml

File

advagg_validator/src/Form/CssW3Form.php, line 19

Namespace

Drupal\advagg_validator\Form
View source
class CssW3Form extends BaseValidatorForm {

  /**
   * The Guzzle HTTP Client.
   *
   * @var \GuzzleHttp\Client
   */
  protected $httpClient;

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

  /**
   * {@inheritdoc}
   *
   * @param \GuzzleHttp\Client $http_client
   *   The Guzzle HTTP Client.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The Drupal renderer.
   */
  public function __construct(ConfigFactoryInterface $config_factory, StateInterface $advagg_files, StateInterface $advagg_aggregates, RequestStack $request_stack, Client $http_client, RendererInterface $renderer) {
    parent::__construct($config_factory, $advagg_files, $advagg_aggregates, $request_stack);
    $this->requestStack = $request_stack;
    $this->httpClient = $http_client;
    $this->renderer = $renderer;
  }

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

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

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::generateForm('css', FALSE);
    $form['notice'] = [
      '#markup' => '<div>' . t('Notice: The form below will submit files to the <a href="http://jigsaw.w3.org/css-validator/">http://jigsaw.w3.org/css-validator/</a> service if used.') . '</div>',
      '#weight' => -1,
    ];
    $form = parent::buildForm($form, $form_state);
    unset($form['actions']);
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitCheckAll(array &$form, FormStateInterface $form_state) {
    $dir = $form_state
      ->getTriggeringElement()['#name'];
    $files = [];
    foreach ($form_state
      ->getValues() as $key => $value) {
      if (strpos($key, 'hidden') === FALSE || strpos($value, $dir) === FALSE || $dir === '.' && substr_count($value, '/') > 0) {
        continue;
      }
      $files[] = $value;
    }

    // Check list.
    $info = $this
      ->testFiles($files);
    $info = $this
      ->hideGoodFiles($info);
    $output = [
      '#theme' => 'item_list',
      '#items' => $info,
    ];
    drupal_set_message($this->renderer
      ->render($output));
  }

  /**
   * Display validation 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 ajaxCheck(array &$form, FormStateInterface $form_state) {
    $dir = $form_state
      ->getTriggeringElement()['#name'];
    return $this
      ->getElement($form, explode('/', $dir))['wrapper'];
  }

  /**
   * {@inheritdoc}
   */
  public function submitCheckDirectory(array &$form, FormStateInterface $form_state) {
    $dir = $form_state
      ->getTriggeringElement()['#name'];
    $files = [];
    $slash_count = substr_count('/' . $dir, '/');
    foreach ($form_state
      ->getValues() as $key => $value) {
      if (strpos($key, 'hidden') === FALSE || strpos($value, $dir) === FALSE || substr_count($value, '/') > $slash_count || $dir === '.' && substr_count($value, '/') > 0) {
        continue;
      }
      $files[] = $value;
    }

    // Check list.
    $info = $this
      ->testFiles($files);
    $info = $this
      ->hideGoodFiles($info);
    $output = [
      '#theme' => 'item_list',
      '#items' => $info,
    ];
    drupal_set_message($this->renderer
      ->render($output));
  }

  /**
   * {@inheritdoc}
   */
  protected function testFiles(array $files, array $options = []) {
    $output = [];
    $file_info = $this->advaggFiles
      ->getMultiple($files);
    foreach ($files as $filename) {

      // Skip missing files.
      if (!file_exists($filename)) {
        continue;
      }
      $file_contents = file_get_contents($filename);
      $lines = file($filename);
      $content_hash = Crypt::hashBase64($file_contents);

      // If saved file information not current update filestore.
      if ($file_info[$filename]['content_hash'] != $content_hash) {
        $this->advagg_files
          ->scanFile($filename, $file_info[$filename], $file_contents);
      }

      // If saved validation results available use them rather than re-run.
      if (isset($file_info[$filename]['validation']['w3'])) {
        $output[$filename]['jigsaw.w3.org'] = $file_info[$filename]['validation']['w3'];
        continue;
      }

      // Run jigsaw.w3.org validator.
      $output[$filename]['jigsaw.w3.org'] = $this
        ->testW3C($filename, $options);

      // Get extra context for errors.
      if (!empty($output[$filename]['jigsaw.w3.org']['errors'])) {
        foreach ($output[$filename]['jigsaw.w3.org']['errors'] as &$value) {
          if (isset($value['line'])) {
            $value['linedata'] = $lines[$value['line'] - 1];
            if (strlen($value['linedata']) > 512) {
              unset($value['linedata']);
            }
          }
        }
        unset($value);
      }
      if (!empty($output[$filename]['jigsaw.w3.org']['warnings'])) {
        foreach ($output[$filename]['jigsaw.w3.org']['warnings'] as &$value) {
          if (isset($value['line'])) {
            $value['linedata'] = $lines[$value['line'] - 1];
            if (strlen($value['linedata']) > 512) {
              unset($value['linedata']);
            }
          }
        }
        unset($value);
      }

      // Save data.
      $file_info[$filename]['validation']['w3'] = $output[$filename]['jigsaw.w3.org'];
      $this->advaggFiles
        ->set($filename, $file_info[$filename]);
    }
    return $output;
  }

  /**
   * Given a CSS file, test to make sure it is valid CSS.
   *
   * @param string $filename
   *   The name of the file.
   * @param array $validator_options
   *   List of options to pass along to the CSS Validator.
   *
   * @return array
   *   Info from the w3c server.
   */
  private function testW3C($filename, array &$validator_options = []) {

    // Get CSS files contents.
    $validator_options['text'] = file_get_contents($filename);
    if (strlen($validator_options['text']) > 50000) {
      unset($validator_options['text']);
      $validator_options['uri'] = $this->requestStack
        ->getCurrentRequest()
        ->getBaseUrl() . $filename;
    }

    // Add in defaults.
    $validator_options += [
      'output' => 'soap12',
      'warning' => '1',
      'profile' => 'css3',
      'usermedium' => 'all',
      'lang' => 'en',
    ];

    // Build request URL.
    // API Documentation http://jigsaw.w3.org/css-validator/api.html
    $request_url = 'http://jigsaw.w3.org/css-validator/validator';
    $query = http_build_query($validator_options, '', '&');
    $url = $request_url . '?' . $query;
    try {
      $data = $this->httpClient
        ->get($url)
        ->getBody();
    } catch (RequestException $e) {
      watchdog_exception('AdvAgg Validator', $e);
    } catch (\Exception $e) {
      watchdog_exception('AdvAgg Validator', $e);
    }
    if (!empty($data)) {

      // Parse XML and return info.
      $return = $this
        ->parseSoapResponse($data);
      $return['filename'] = $filename;
      if (isset($validator_options['text'])) {
        unset($validator_options['text']);
      }
      elseif (isset($validator_options['uri'])) {
        unset($validator_options['uri']);
      }
      $return['options'] = $validator_options;
      return $return;
    }
    return [
      'error' => t('W3C Server did not return a 200 or request data was empty.'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  private function parseSoapResponse($xml) {
    $doc = new DOMDocument();
    $response = [];

    // Try to load soap 1.2 XML response, and suppress warning reports if any.
    if (!@$doc
      ->loadXML($xml)) {

      // Could not load the XML document.
      return $response;
    }

    // Get the standard CDATA elements.
    $cdata = [
      'uri',
      'checkedby',
      'csslevel',
      'date',
    ];
    foreach ($cdata as $var) {
      $element = $doc
        ->getElementsByTagName($var);
      if ($element->length) {
        $response[$var] = $element
          ->item(0)->nodeValue;
      }
    }

    // Handle the element validity and get errors if not valid.
    $element = $doc
      ->getElementsByTagName('validity');
    if ($element->length && $element
      ->item(0)->nodeValue === 'true') {
      $response['validity'] = TRUE;
    }
    else {
      $response['validity'] = FALSE;
      $errors = $doc
        ->getElementsByTagName('error');
      foreach ($errors as $error) {
        $response['errors'][] = $this
          ->domExtractor($error);
      }
    }

    // Get warnings.
    $warnings = $doc
      ->getElementsByTagName('warning');
    foreach ($warnings as $warning) {
      $response['warnings'][] = $this
        ->domExtractor($warning);
    }

    // Return response array.
    return $response;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AdvaggFormBase::$advaggAggregates protected property The AdvAgg aggregates state information storage service.
AdvaggFormBase::$advaggFiles protected property The AdvAgg file status state information storage service.
AdvaggFormBase::$requestStack protected property The request stack. Overrides FormBase::$requestStack
AdvaggFormBase::isAjax protected function Checks if the form was submitted by AJAX.
BaseValidatorForm::domExtractor protected function Extract info from the DOMNode Object.
BaseValidatorForm::generateForm public function Generate a heirachical form sorted by path from asset files.
BaseValidatorForm::getEditableConfigNames protected function Gets the configuration names that will be editable. Overrides ConfigFormBaseTrait::getEditableConfigNames
BaseValidatorForm::getElement protected function Get array element that corresponds to directory.
BaseValidatorForm::hideGoodFiles protected function Do not display info on a file if it is valid.
BaseValidatorForm::scanAllDirs protected function Recursively scan the drupal webroot for files matching the given extension.
BaseValidatorForm::scanDirectory protected function Finds all files that match a given mask in a given directory.
ConfigFormBase::submitForm public function Form submission handler. Overrides FormInterface::submitForm 26
ConfigFormBaseTrait::config protected function Retrieves a configuration object.
CssW3Form::$httpClient protected property The Guzzle HTTP Client.
CssW3Form::$renderer protected property The Drupal renderer.
CssW3Form::ajaxCheck public function Display validation info via ajax callback.
CssW3Form::buildForm public function Form constructor. Overrides ConfigFormBase::buildForm
CssW3Form::create public static function Instantiates a new instance of this class. Overrides AdvaggFormBase::create
CssW3Form::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
CssW3Form::parseSoapResponse private function
CssW3Form::submitCheckAll public function
CssW3Form::submitCheckDirectory public function
CssW3Form::testFiles protected function Perform server side test(s) on all given files. Overrides BaseValidatorForm::testFiles
CssW3Form::testW3C private function Given a CSS file, test to make sure it is valid CSS.
CssW3Form::__construct public function Overrides AdvaggFormBase::__construct
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::configFactory protected function Gets the config factory for this form. 1
FormBase::container private function Returns the service container.
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.
FormBase::validateForm public function Form validation handler. Overrides FormInterface::validateForm 62
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
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.