Completed
Push — master ( 1857e6...d96bec )
by Joao
03:02
created

src/Database/DBDblibFunctions.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace ByJG\AnyDataset\Database;
4
5
use ByJG\AnyDataset\Exception\NotAvailableException;
6
use ByJG\AnyDataset\Repository\DBDataset;
7
8
class DBDblibFunctions extends DBBaseFunctions
9
{
10
11 View Code Duplication
    function concat($s1, $s2 = null)
12
    {
13
        for ($i = 0, $numArgs = func_num_args(); $i < $numArgs; $i++) {
14
            $var = func_get_arg($i);
15
            $sql .= ($i == 0 ? "" : "+") . $var;
0 ignored issues
show
The variable $sql does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
16
        }
17
18
        return $sql;
19
    }
20
21
    /**
22
     * Given a SQL returns it with the proper LIMIT or equivalent method included
23
     * @param string $sql
24
     * @param int $start
25
     * @param int $qty
26
     * @return string
27
     */
28
    function limit($sql, $start, $qty)
29
    {
30
        throw new NotAvailableException("DBLib does not support LIMIT feature.");
31
    }
32
33
    /**
34
     * Given a SQL returns it with the proper TOP or equivalent method included
35
     * @param string $sql
36
     * @param int $qty
37
     * @return string
38
     */
39
    function top($sql, $qty)
40
    {
41
        return preg_replace("/^\s*(select) /i", "\\1 top $qty ", $sql);
42
    }
43
44
    /**
45
     * Return if the database provider have a top or similar function
46
     * @return unknown_type
47
     */
48
    function hasTop()
49
    {
50
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type declared by the interface ByJG\AnyDataset\Database...ctionsInterface::hasTop of type ByJG\AnyDataset\Database\unknown_type.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
51
    }
52
53
    /**
54
     * Return if the database provider have a limit function
55
     * @return bool
56
     */
57
    function hasLimit()
58
    {
59
        return false;
60
    }
61
62
    /**
63
     * Format date column in sql string given an input format that understands Y M D
64
     * @param string $fmt
65
     * @param string $col
66
     * @return string
67
     * @example $db->getDbFunctions()->SQLDate("d/m/Y H:i", "dtcriacao")
68
     */
69
    function sqlDate($fmt, $col = false)
70
    {
71
        if (!$col) $col = "getdate()";
0 ignored issues
show
Bug Best Practice introduced by
The expression $col of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
72
        $s = '';
73
74
        $len = strlen($fmt);
75
        for ($i = 0; $i < $len; $i++) {
76
            if ($s) $s .= '+';
77
            $ch = $fmt[$i];
78
            switch ($ch) {
79
                case 'Y':
80
                case 'y':
81
                    $s .= "datename(yyyy,$col)";
82
                    break;
83
                case 'M':
84
                    $s .= "convert(char(3),$col,0)";
85
                    break;
86
                case 'm':
87
                    $s .= "replace(str(month($col),2),' ','0')";
88
                    break;
89
                case 'Q':
90
                case 'q':
91
                    $s .= "datename(quarter,$col)";
92
                    break;
93
                case 'D':
94
                case 'd':
95
                    $s .= "replace(str(day($col),2),' ','0')";
96
                    break;
97
                case 'h':
98
                    $s .= "substring(convert(char(14),$col,0),13,2)";
99
                    break;
100
101
                case 'H':
102
                    $s .= "replace(str(datepart(hh,$col),2),' ','0')";
103
                    break;
104
105
                case 'i':
106
                    $s .= "replace(str(datepart(mi,$col),2),' ','0')";
107
                    break;
108
                case 's':
109
                    $s .= "replace(str(datepart(ss,$col),2),' ','0')";
110
                    break;
111
                case 'a':
112
                case 'A':
113
                    $s .= "substring(convert(char(19),$col,0),18,2)";
114
                    break;
115
116 View Code Duplication
                default:
117
                    if ($ch == '\\') {
118
                        $i++;
119
                        $ch = substr($fmt, $i, 1);
120
                    }
121
                    $s .= $this->qstr($ch);
122
                    break;
123
            }
124
        }
125
        return $s;
126
    }
127
128
    /**
129
     * Format a string date to a string database readable format.
130
     *
131
     * @param string $date
132
     * @param string $dateFormat
133
     * @return string
134
     */
135
    function toDate($date, $dateFormat)
136
    {
137
        return parent::toDate($date, $dateFormat);
138
    }
139
140
    /**
141
     * Format a string database readable format to a string date in a free format.
142
     *
143
     * @param string $date
144
     * @param string $dateFormat
145
     * @return string
146
     */
147
    function fromDate($date, $dateFormat)
148
    {
149
        return parent::fromDate($date, $dateFormat);
150
    }
151
152
    /**
153
     *
154
     * @param DBDataset $dbdataset
155
     * @param string $sql
156
     * @param array $param
157
     * @return int
158
     */
159 View Code Duplication
    function executeAndGetInsertedId($dbdataset, $sql, $param)
160
    {
161
        $id = parent::executeAndGetInsertedId($dbdataset, $sql, $param);
162
        $it = $dbdataset->getIterator("select @@identity id");
163
        if ($it->hasNext()) {
164
            $sr = $it->moveNext();
165
            $id = $sr->getField("id");
166
        }
167
168
        return $id;
169
    }
170
}
171