MySqlQueryErrorException   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Test Coverage

Coverage 15.79%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
dl 0
loc 86
ccs 3
cts 19
cp 0.1579
rs 10
c 1
b 0
f 0
wmc 7

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A styledQuery() 0 33 4
A isQueryError() 0 3 1
A composerMessage() 0 6 1
1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Stratum\MySql\Exception;
5
6
use SetBased\Stratum\Middle\Exception\QueryErrorException;
7
use Symfony\Component\Console\Formatter\OutputFormatter;
8
9
/**
10
 * Exception thrown when the execution of MySQL query fails.
11
 */
12
class MySqlQueryErrorException extends MySqlDataLayerException implements QueryErrorException
13
{
14
  //--------------------------------------------------------------------------------------------------------------------
15
  /**
16
   * The failed query.
17
   *
18
   * @var string
19
   */
20
  protected string $query;
21
22
  //--------------------------------------------------------------------------------------------------------------------
23
  /**
24
   * Object constructor.
25
   *
26
   * @param int    $errno  The error code value of the error ($mysqli->errno).
27
   * @param string $error  Description of the last error ($mysqli->error).
28
   * @param string $method The name of the executed method.
29
   * @param string $query  The failed query.
30
   */
31 5
  public function __construct(int $errno, string $error, string $method, string $query)
32
  {
33 5
    $this->query = $query;
34
35 5
    parent::__construct($errno, $error, $method);
36
  }
37
38
  //--------------------------------------------------------------------------------------------------------------------
39
  /**
40
   * Returns whether this exception is caused by an invalid SQL statement.
41
   */
42
  public function isQueryError(): bool
43
  {
44
    return ($this->errno===1064);
45
  }
46
47
  //--------------------------------------------------------------------------------------------------------------------
48
  /**
49
   * Returns an array with the lines of the SQL statement. The line where the error occurred will be styled.
50
   *
51
   * @param string $style The style for highlighting the line with error.
52
   */
53
  public function styledQuery(string $style = 'error'): array
54
  {
55
    $query = trim($this->query); // MySQL ignores leading whitespace in queries.
56
57
    if ($this->isQueryError())
58
    {
59
      // Query is a multi line query.
60
      // The format of a 1064 message is: %s near '%s' at line %d
61
      $errorLineNumber = trim(strrchr($this->error, ' '));
62
63
      // Prepend each line with line number.
64
      $lines   = explode(PHP_EOL, $query);
65
      $digits  = ceil(log(sizeof($lines) + 1, 10));
66
      $format  = sprintf('%%%dd %%s', $digits);
67
      $message = [];
68
      foreach ($lines as $i => $line)
69
      {
70
        if (($i + 1)===$errorLineNumber)
71
        {
72
          $message[] = sprintf('<%s>'.$format.'</%s>', $style, $i + 1, OutputFormatter::escape($line), $style);
73
        }
74
        else
75
        {
76
          $message[] = sprintf($format, $i + 1, OutputFormatter::escape($line));
77
        }
78
      }
79
    }
80
    else
81
    {
82
      $message = explode(PHP_EOL, $query);
83
    }
84
85
    return $message;
86
  }
87
88
  //--------------------------------------------------------------------------------------------------------------------
89
  /**
90
   * Composes the message of this exception as array of lines.
91
   */
92
  protected function composerMessage(): array
93
  {
94
    return array_merge($this->splitIntoTwoColumns('MySQL Errno', (string)$this->errno),
95
                       $this->splitIntoTwoColumns('Error', $this->error),
96
                       $this->splitIntoTwoColumns('Query', $this->query),
97
                       $this->splitIntoTwoColumns('Method', $this->method));
98 5
  }
99
100 5
  //--------------------------------------------------------------------------------------------------------------------
101 5
}
102 5
103
//----------------------------------------------------------------------------------------------------------------------
104