Passed
Pull Request — master (#70)
by Christian
01:30
created

DatabaseSelect::cacheUpdateRequired()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 5
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 10
rs 9.6111
1
<?php
2
namespace Maphper\DataSource;
3
4
class DatabaseSelect {
5
    private $resultCache = [];
6
    private $idCache = [];
7
    private $idCacheTime = [];
8
    private $selectBuilder;
9
    private $whereBuilder;
10
    private $adapter;
11
    private $databaseModify;
12
    private $defaultSort;
13
    private $table;
14
15
    public function __construct(DatabaseAdapter $adapter, DatabaseModify $databaseModify, $table, $defaultSort, $cacheMode) {
16
        $this->adapter = $adapter;
17
        $this->databaseModify = $databaseModify;
18
        $this->selectBuilder = new \Maphper\Lib\SelectBuilder();
19
        $this->whereBuilder = new \Maphper\Lib\Sql\WhereBuilder();
20
        $this->defaultSort = $defaultSort;
21
        $this->cacheMode = $cacheMode;
0 ignored issues
show
Bug Best Practice introduced by
The property cacheMode does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
22
        $this->table = $table;
23
    }
24
25
    private function cacheUpdateRequired($id) {
26
      if ($this->cacheMode > 0) {
27
        if (!isset($this->idCacheTime[$id])) return true; // Cache time has not been set for first time
28
29
        if (time() - $this->idCacheTime[$id] > $this->cacheMode) return true; // Cache time has expired
30
      }
31
32
      if (!isset($this->idCache[$id])) return true; // Cache has not been set for first time
33
34
      return false;
35
    }
36
37
  public function findById($id, $pk) {
38
		if ($this->cacheMode < 0 || $this->cacheUpdateRequired($id)) {
39
			try {
40
				$result = $this->selectQuery($this->selectBuilder->select($this->table, $pk . ' = :id', [':id' => $id], ['limit' => 1]));
41
			}
42
			catch (\Exception $e) {
43
                // Don't issue an error if it cannot be found since we return null
44
			}
45
46
			if (isset($result[0])) $result = $result[0];
47
			else return null;
48
		}
49
50
    if ($this->cacheMode < 0) return $result; // Cache mode is off
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
51
52
    if ($this->cacheUpdateRequired()) {
0 ignored issues
show
Bug introduced by
The call to Maphper\DataSource\Datab...::cacheUpdateRequired() has too few arguments starting with id. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

52
    if ($this->/** @scrutinizer ignore-call */ cacheUpdateRequired()) {

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
53
      $this->idCache[$id] = $result;
54
      $this->idCacheTime[$id] = time();
55
    }
56
57
		return $this->idCache[$id];
58
	}
59
60
  public function findByField(array $fields, $options = []) {
61
		$cacheId = md5(serialize(func_get_args()));
62
63
    if ($this->cacheMode < 0 || $this->cacheUpdateRequired($cacheId)) {
64
			$query = $this->whereBuilder->createSql($fields);
65
66
			if (!isset($options['order'])) $options['order'] = $this->defaultSort;
67
68
			try {
69
				$result = $this->selectQuery($this->selectBuilder->select($this->table, $query['sql'], $query['args'], $options));
70
				$this->databaseModify->addIndex(array_keys($query['args']));
71
				$this->databaseModify->addIndex(explode(',', $options['order']));
72
			}
73
			catch (\Exception $e) {
74
				$this->errors[] = $e;
0 ignored issues
show
Bug Best Practice introduced by
The property errors does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
75
				$result = [];
76
			}
77
		}
78
79
    if ($this->cacheMode < 0) return $result; // Cache mode is off
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
80
81
    if ($this->cacheUpdateRequired($cacheId)) {
82
      $this->idCache[$cacheId] = $result;
83
      $this->idCacheTime[$cacheId] = time();
84
    }
85
86
		return $this->idCache[$cacheId];
87
	}
88
89
    public function findAggregate($function, $field, $group = null, array $criteria = [], array $options = []) {
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

89
    public function findAggregate($function, $field, $group = null, array $criteria = [], /** @scrutinizer ignore-unused */ array $options = []) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
90
		//Cannot count/sum/max multiple fields, pick the first one. This should only come into play when trying to count() a mapper with multiple primary keys
91
		if (is_array($field)) $field = $field[0];
92
		$query = $this->whereBuilder->createSql($criteria);
93
94
		try {
95
			$this->databaseModify->addIndex(array_keys($query['args']));
96
			$this->databaseModify->addIndex(explode(',', $group));
97
			$result = $this->selectQuery($this->selectBuilder->aggregate($this->table, $function, $field, $query['sql'], $query['args'], $group));
98
99
			return $this->determineAggregateResult($result, $group, $field);
100
		}
101
		catch (\Exception $e) {
102
			return $group ? [] : 0;
103
		}
104
	}
105
106
    private function determineAggregateResult($result, $group, $field) {
107
        if ($group != null) {
108
            $ret = [];
109
            foreach ($result as $res) $ret[$res->$field] = $res->val;
110
            return $ret;
111
        }
112
        else if (isset($result[0])) return $result[0]->val;
113
        else return 0;
114
    }
115
116
    private function selectQuery(\Maphper\Lib\Query $query) {
117
        return $this->adapter->query($query)->fetchAll(\PDO::FETCH_OBJ);
118
    }
119
120
    public function clearResultCache() {
121
        if ($this->cacheMode >= 0) $this->resultCache = [];
122
    }
123
124
    public function clearIDCache() {
125
        if ($this->cacheMode >= 0) $this->idCache = [];
126
    }
127
128
    public function updateCache($data, $pkValue) {
129
        if ($this->cacheMode >= 0) {
130
  		    if (isset($this->cache[$pkValue])) $this->cache[$pkValue] = (object) array_merge((array)$this->cache[$pkValue], (array)$data);
0 ignored issues
show
Bug Best Practice introduced by
The property cache does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
131
  		    else $this->cache[$pkValue] = $data;
132
        }
133
    }
134
135
    public function deleteIDFromCache($id) {
136
        if ($this->cacheMode >= 0) {
137
          unset($this->idCache[$id]);
138
          unset($this->idCacheTime[$id]);
139
        }
140
    }
141
}
142