Passed
Push — master ( 151185...42f330 )
by P.R.
04:09
created

MySqlQueryErrorException::isQueryError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 1
b 0
f 0
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 true if this exception is caused by an invalid SQL statement. Otherwise returns false.
41
   *
42
   * @return bool
43
   */
44
  public function isQueryError(): bool
45
  {
46
    return ($this->errno===1064);
47
  }
48
49
  //--------------------------------------------------------------------------------------------------------------------
50
  /**
51
   * Returns an array with the lines of the SQL statement. The line where the error occurred will be styled.
52
   *
53
   * @param string $style The style for highlighting the line with error.
54
   *
55
   * @return array The lines of the SQL statement.
56
   */
57
  public function styledQuery(string $style = 'error'): array
58
  {
59
    $query = trim($this->query); // MySQL ignores leading whitespace in queries.
60
61
    if ($this->isQueryError())
62
    {
63
      // Query is a multi line query.
64
      // The format of a 1064 message is: %s near '%s' at line %d
65
      $errorLineNumber = trim(strrchr($this->error, ' '));
66
67
      // Prepend each line with line number.
68
      $lines   = explode(PHP_EOL, $query);
69
      $digits  = ceil(log(sizeof($lines) + 1, 10));
70
      $format  = sprintf('%%%dd %%s', $digits);
71
      $message = [];
72
      foreach ($lines as $i => $line)
73
      {
74
        if (($i + 1)==$errorLineNumber)
75
        {
76
          $message[] = sprintf('<%s>'.$format.'</%s>', $style, $i + 1, OutputFormatter::escape($line), $style);
77
        }
78
        else
79
        {
80
          $message[] = sprintf($format, $i + 1, OutputFormatter::escape($line));
81
        }
82
      }
83
    }
84
    else
85
    {
86
      $message = explode(PHP_EOL, $query);
87
    }
88
89
    return $message;
90
  }
91
92
  //--------------------------------------------------------------------------------------------------------------------
93
  /**
94
   * Composes the message of this exception as array of lines.
95
   *
96
   * @return array
97
   */
98 5
  protected function composerMessage(): array
99
  {
100 5
    return array_merge($this->splitIntoTwoColumns('MySQL Errno', (string)$this->errno),
101 5
                       $this->splitIntoTwoColumns('Error', $this->error),
102 5
                       $this->splitIntoTwoColumns('Query', $this->query),
103 5
                       $this->splitIntoTwoColumns('Method', $this->method));
104
  }
105
106
  //--------------------------------------------------------------------------------------------------------------------
107
}
108
109
//----------------------------------------------------------------------------------------------------------------------
110