Version 1
[yaffs-website] / web / modules / contrib / advagg / advagg_validator / src / Form / CssW3Form.php
diff --git a/web/modules/contrib/advagg/advagg_validator/src/Form/CssW3Form.php b/web/modules/contrib/advagg/advagg_validator/src/Form/CssW3Form.php
new file mode 100644 (file)
index 0000000..28508b3
--- /dev/null
@@ -0,0 +1,314 @@
+<?php
+
+namespace Drupal\advagg_validator\Form;
+
+use DOMDocument;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Core\State\StateInterface;
+use Drupal\Component\Utility\Crypt;
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\RequestException;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Configure form for W3C validation of CSS files.
+ */
+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;
+  }
+
+}