You are here

function _coder_read_and_parse_file in Coder 6.2

Same name and namespace in other branches
  1. 5.2 coder.module \_coder_read_and_parse_file()
  2. 5 coder.module \_coder_read_and_parse_file()
  3. 6 coder.module \_coder_read_and_parse_file()

Parse and read a file into a format easy to validate.

Parameters

$coder_args: Coder arguments array variable to add file lines of code (with trailing newlines. The following array indices are added: '#all_array_lines', '#php_array_lines', '#allphp_array_lines', '#html_array_lines', '#quote_array_lines', '#doublequote_array_lines', '#comment_array_lines', and #all_lines. The _array_ variants are multidimensional arrays, the first index for the line number, and the second index for each occurance within the line. #all_lines is a simple array, with each line from the file as an index.

Return value

Integer 1 if success.

1 call to _coder_read_and_parse_file()
do_coder_reviews in ./coder.module
Perform batch coder reviews for multiple files.

File

./coder.module, line 1089

Code

function _coder_read_and_parse_file(&$coder_args) {
  $is_php_file = 1;
  $regex = '/(' . implode('|', array_merge(array(
    'module',
  ), $coder_args['#php_extensions'])) . ')$/';
  if (!preg_match($regex, $coder_args['#filename'])) {
    $is_php_file = 0;

    /*
    // If this isn't a php file, then don't try to parse it.
    if ((($filepath = realpath($coder_args['#filename'])) && file_exists($filepath))) {
      $full_lines = file($filepath);
      if ($full_lines[0] != '<?php') {
        foreach ($full_lines as $lineno => $line) {
          if (($line = trim($line, "\r\n")) != '') {
            $all_lines[$lineno] = $line;
          }
        }
        $coder_args['#all_lines'] = $all_lines;
        return 1;
      }
    }
    */
  }

  // Get the path to the module file.
  if (!empty($coder_args['#patch']) || !empty($coder_args['#test']) || ($filepath = realpath($coder_args['#filename'])) && file_exists($filepath)) {
    $in_php = $is_php_file ? 0 : 1;
    $in_allphp = $is_php_file ? 0 : 1;
    $in_comment = 0;
    if (!empty($coder_args['#patch'])) {
      $content = $coder_args['#patch'];
      if (preg_match('/^\\s*\\*/', $content)) {
        $in_comment = '*';
      }
      else {
        $content = preg_replace('/^(function\\s.*?(\\r\\n|\\n)+)(\\s*\\*)/', '${1}/*', $content);
        $in_php = 1;
        $in_allphp = 1;
      }
    }
    elseif (!empty($coder_args['#test'])) {
      $content = $coder_args['#test'];
      $in_php = 1;
      $in_allphp = 1;
    }
    else {
      $content = file_get_contents($filepath) . "\n";
    }
    $content_length = drupal_strlen($content);
    $in_comment = 0;
    $beginning_of_line = 0;
    $in_quote_html = 0;
    $in_backslash = 0;
    $in_quote = 0;
    $in_heredoc = 0;
    $in_heredoc_html = '';
    $heredoc = '';
    $all_lines = array();
    $full_lines = array();
    $php_lines = array();
    $allphp_lines = array();
    $html_lines = array();
    $quote_lines = array();
    $doublequote_lines = array();
    $comment_lines = array();
    $this_all_lines = '';
    $this_php_lines = '';
    $this_allphp_lines = '';
    $this_html_lines = '';
    $this_quote_lines = array(
      '',
    );
    $this_quote_index = -1;
    $this_quote_sep = FALSE;
    $this_doublequote_lines = array(
      '',
    );
    $this_doublequote_index = -1;
    $this_comment_lines = '';

    // Parse the file:
    // - Strip comments,
    // - Strip quote content,
    // - Strip stuff not in php,
    // - Break into lines.
    $lineno = 1;
    for ($pos = 0; $pos < $content_length; $pos++) {

      // Get the current character.
      $char = $content[$pos];
      if ($char == "\n") {
        if ($in_comment === '/') {

          // End C++ style comments on newline.
          $in_comment = 0;
        }

        // Assume that html inside quotes doesn't span newlines.
        $in_quote_html = 0;

        // Remove blank lines now, so we avoid processing them over-and-over.
        if ($this_all_lines != '') {
          if (trim($this_all_lines, "\r\n") != '') {
            $all_lines[$lineno] = array(
              $this_all_lines,
            );
            $full_lines[$lineno] = $this_all_lines;
          }
          if (trim($this_php_lines, "\r\n") != '') {
            $php_lines[$lineno] = array(
              $this_php_lines,
            );
          }
          if (trim($this_allphp_lines, "\r\n") != '') {
            $allphp_lines[$lineno] = array(
              $this_allphp_lines,
            );
          }
          if (trim($this_html_lines, "\r\n") != '') {
            $html_lines[$lineno] = array(
              $this_html_lines,
            );
          }
          $quotes = array();
          foreach ($this_quote_lines as $quote_line) {
            if (trim($quote_line, "\r\n") != '') {
              $quotes[] = $quote_line;
            }
          }
          if (count($quotes)) {
            $quote_lines[$lineno] = $quotes;
          }
          $quotes = array();
          foreach ($this_doublequote_lines as $quote_line) {
            if (trim($quote_line, "\r\n") != '') {
              $quotes[] = $quote_line;
            }
          }
          if (count($quotes)) {
            $doublequote_lines[$lineno] = $quotes;
          }
          if (trim($this_comment_lines, "\r\n") != '') {
            $comment_lines[$lineno] = array(
              $this_comment_lines,
            );
          }
        }

        // Save this line and start a new line.
        $lineno++;
        $this_all_lines = '';
        $this_php_lines = '';
        $this_allphp_lines = '';
        $this_html_lines = '';
        $this_quote_lines = array(
          '',
        );
        $this_doublequote_lines = array(
          '',
        );
        $this_quote_index = -1;
        $this_quote_sep = FALSE;
        $this_doublequote_index = -1;
        $this_comment_lines = '';
        $beginning_of_line = 1;
        continue;
      }
      if ($this_all_lines != '') {
        $beginning_of_line = 0;
      }
      $this_all_lines .= $char;
      if ($in_php || $in_allphp) {

        // When in a quoted string, look for the trailing quote
        // strip characters in the string, replacing with '' or "".
        if ($in_quote) {
          if ($in_backslash) {
            $in_backslash = 0;
          }
          elseif ($char == '\\') {
            $in_backslash = 1;
          }
          elseif ($char == $in_quote && !$in_backslash) {
            $in_quote = 0;
          }
          elseif ($char == '<') {
            $in_quote_html = '>';
          }
          if ($in_quote) {
            if ($this_quote_index == -1) {
              $this_quote_index = 0;
            }
            $this_quote_lines[$this_quote_index] .= $char;
            if ($in_quote == '"') {
              if ($this_doublequote_index == -1) {
                $this_doublequote_index = 0;
              }
              $this_doublequote_lines[$this_doublequote_index] .= $char;
            }
            if ($in_quote_html) {
              $this_html_lines .= $char;
            }
          }
          if ($char == $in_quote_html) {
            $in_quote_html = 0;
          }
          $this_allphp_lines .= $char;
          unset($char);

          // NOTE: Trailing char output with starting one.
        }
        elseif ($in_heredoc) {
          if ($beginning_of_line && $char == $in_heredoc[0] && drupal_substr($content, $pos, $in_heredoc_length) == $in_heredoc) {
            $this_all_lines .= drupal_substr($content, $pos + 1, $in_heredoc_length - 1);
            $in_heredoc = 0;
            $pos += $in_heredoc_length;
          }
          elseif ($char == '<') {
            $in_heredoc_html = '>';
          }
          if ($in_heredoc && $in_heredoc_html) {
            $this_html_lines .= $char;
          }
          if ($in_heredoc_html && $char == $in_heredoc_html) {
            $in_heredoc_html = '';
          }
          unset($char);
        }
        elseif ($char == '?' && $content[$pos + 1] == '>' && $in_comment !== '*') {
          unset($char);
          $in_php = 0;
          $in_allphp = 0;
          $this_all_lines .= '>';
          $pos++;
        }
        elseif ($in_comment) {
          $this_comment_lines .= $char;
          if ($in_comment == '*' && $char == '*' && $content[$pos + 1] == '/') {
            $in_comment = 0;
            $this_all_lines .= '/';
            $this_comment_lines .= '/';
            $pos++;
          }
          unset($char);

          // Don't add comments to php output.
        }
        else {
          switch ($char) {
            case ',':
            case ')':
            case '(':

              // Look for separators which force a new quote string.
              if ($this_quote_index < 0 || !empty($this_quote_lines[$this_quote_index])) {
                $this_quote_sep = TRUE;
              }
              break;
            case '\'':
            case '"':
              if ($content[$pos - 1] != '\\') {
                $this_php_lines .= $char;
                $in_quote = $char;
                if ($this_quote_sep) {
                  $this_quote_lines[++$this_quote_index] = '';
                  if ($char == '"') {
                    $this_doublequote_lines[++$this_doublequote_index] = '';
                  }
                }
                $this_quote_sep = FALSE;
              }
              break;
            case '/':
              $next_char = $content[$pos + 1];
              if ($next_char == '/' || $next_char == '*') {
                unset($char);
                $in_comment = $next_char;
                $this_all_lines .= $next_char;
                $this_comment_lines .= '/' . $next_char;
                $pos++;
              }
              break;
            case '<':
              if ($content[$pos + 1] == '<' && $content[$pos + 2] == '<') {
                unset($char);
                $this_all_lines .= '<<';

                // Get the heredoc word.
                // Read until the end-of-line.
                for ($pos += 3; $pos < $content_length; $pos++) {
                  $char = $content[$pos];
                  if ($char == "\n") {
                    $pos--;
                    if (preg_match('/^\\s*(\\w+)/', $heredoc, $match)) {
                      $in_heredoc = $match[1];
                      $in_heredoc_length = drupal_strlen($in_heredoc);
                    }
                    break;
                  }
                  $this_all_lines .= $char;
                  $heredoc .= $char;
                }
                $heredoc = '';

                // Replace heredoc's with an empty string.
                $this_php_lines .= '\'\'';
                $this_allphp_lines .= '\'\'';
                unset($char);
              }
              break;
          }
        }
        if (isset($char)) {
          $this_php_lines .= $char;
          $this_allphp_lines .= $char;
        }
      }
      else {
        switch ($char) {
          case '<':
            if ($content[$pos + 1] == '?') {
              if ($content[$pos + 2] == ' ') {
                $in_php = 1;
                $in_allphp = 1;
                $this_all_lines .= '? ';
                $pos += 2;
              }
              elseif (drupal_substr($content, $pos + 2, 3) == 'php') {
                $in_php = 1;
                $in_allphp = 1;
                $this_all_lines .= '?php';
                $pos += 4;
              }
              break;
            }

          // FALLTHROUGH
          default:
            $this_html_lines .= $char;
            break;
        }
      }
    }
    if (trim($this_all_lines) != '') {
      $all_lines[$lineno] = array(
        $this_all_lines,
      );
      $full_lines[$lineno] = $this_all_lines;
    }
    if (trim($this_php_lines) != '') {
      $php_lines[$lineno] = array(
        $this_php_lines,
      );
    }
    if (trim($this_allphp_lines) != '') {
      $allphp_lines[$lineno] = array(
        $this_allphp_lines,
      );
    }
    if (trim($this_html_lines) != '') {
      $html_lines[$lineno] = array(
        $this_html_lines,
      );
    }
    $quotes = array();
    foreach ($this_quote_lines as $quote_line) {
      if (trim($quote_line, "\r\n") != '') {
        $quotes[] = $quote_line;
      }
    }
    if (count($quotes)) {
      $quote_lines[$lineno] = $quotes;
    }
    $quotes = array();
    foreach ($this_doublequote_lines as $quote_line) {
      if (trim($quote_line, "\r\n") != '') {
        $quotes[] = $quote_line;
      }
    }
    if (count($quotes)) {
      $doublequote_lines[$lineno] = $quotes;
    }
    if (trim($this_comment_lines) != '') {
      $comment_lines[$lineno] = array(
        $this_comment_lines,
      );
    }

    // Add the files lines to the arguments.
    $coder_args['#all_array_lines'] = $all_lines;
    $coder_args['#php_array_lines'] = $php_lines;
    $coder_args['#allphp_array_lines'] = $allphp_lines;
    $coder_args['#html_array_lines'] = $html_lines;
    $coder_args['#quote_array_lines'] = $quote_lines;
    $coder_args['#doublequote_array_lines'] = $doublequote_lines;
    $coder_args['#comment_array_lines'] = $comment_lines;
    $coder_args['#all_lines'] = $full_lines;
    return 1;
  }
}