Passed
Push — v2 ( e57a7e...6c89a0 )
by Berend
04:02
created
src/ColumnProperty.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -5,10 +5,10 @@
 block discarded – undo
5 5
 
6 6
 class ColumnProperty
7 7
 {
8
-	const NONE = 0;
9
-	const UNIQUE = 1;
10
-	const NOT_NULL = 2;
11
-	const IMMUTABLE = 4;
12
-	const AUTO_INCREMENT = 8;
13
-	const PRIMARY_KEY = 16;
8
+    const NONE = 0;
9
+    const UNIQUE = 1;
10
+    const NOT_NULL = 2;
11
+    const IMMUTABLE = 4;
12
+    const AUTO_INCREMENT = 8;
13
+    const PRIMARY_KEY = 16;
14 14
 }
15 15
\ No newline at end of file
Please login to merge, or discard this patch.
src/Traits/Pagination.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -6,5 +6,5 @@
 block discarded – undo
6 6
 
7 7
 trait Pagination
8 8
 {
9
-	// @TODO: This one would most likely only be relevant for api requests (and perhaps supply a public method for searching with a page)
9
+    // @TODO: This one would most likely only be relevant for api requests (and perhaps supply a public method for searching with a page)
10 10
 }
11 11
\ No newline at end of file
Please login to merge, or discard this patch.
test-bootstrap.php 1 patch
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -9,7 +9,7 @@  discard block
 block discarded – undo
9 9
 // Cleanup SQL
10 10
 $user_delete = "DROP USER IF EXISTS $dbuser@'localhost'; ";
11 11
 $database_delete = "DROP DATABASE IF EXISTS $dbname; ";
12
-$sql_cleanup = $user_delete . $database_delete;
12
+$sql_cleanup = $user_delete.$database_delete;
13 13
 
14 14
 // Setup SQL
15 15
 $db_create = "CREATE DATABASE $dbname; ";
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
 $user_alter = "ALTER USER '$dbuser'@'localhost' IDENTIFIED with mysql_native_password BY '$dbpass'; ";
18 18
 $user_grant = "GRANT ALL PRIVILEGES ON *.* TO '$dbuser'@'localhost';";
19 19
 
20
-$sql_setup = $sql_cleanup . $db_create . $user_create . $user_alter . $user_grant;
20
+$sql_setup = $sql_cleanup.$db_create.$user_create.$user_alter.$user_grant;
21 21
 print $sql_setup;
22 22
 echo "Please enter mysql root password to set up a database environment for testing\n";
23 23
 exec("echo \"$sql_setup\" | mysql -u root -p");
Please login to merge, or discard this patch.
src/Traits/Address.php 1 patch
Indentation   +144 added lines, -144 removed lines patch added patch discarded remove patch
@@ -11,154 +11,154 @@
 block discarded – undo
11 11
 
12 12
 trait Address
13 13
 {
14
-	/** @var string the address line */
15
-	protected $address;
16
-
17
-	/** @var string the zipcode */
18
-	protected $zipcode;
19
-
20
-	/** @var string the city */
21
-	protected $city;
22
-
23
-	/** @var string the country */
24
-	protected $country;
25
-
26
-	/**
27
-	 * Registers the Address trait on the including class
28
-	 * @return void
29
-	 */
30
-	protected function initAddress() 
31
-	{
32
-		$this->extendTableDefinition(TRAIT_ADDRESS_FIELD_ADDRESS, [
33
-			'value' => &$this->address,
34
-			'validate' => null,
35
-			'type' => 'VARCHAR',
36
-			'length' => 1024,
37
-			'properties' => null
38
-		]);
39
-
40
-		$this->extendTableDefinition(TRAIT_ADDRESS_FIELD_ZIPCODE, [
41
-			'value' => &$this->zipcode,
42
-			'validate' => null,
43
-			'type' => 'VARCHAR',
44
-			'length' => 1024,
45
-			'properties' => null
46
-		]);
47
-
48
-		$this->extendTableDefinition(TRAIT_ADDRESS_FIELD_CITY, [
49
-			'value' => &$this->city,
50
-			'validate' => null,
51
-			'type' => 'VARCHAR',
52
-			'length' => 1024,
53
-			'properties' => null
54
-		]);
55
-
56
-		$this->extendTableDefinition(TRAIT_ADDRESS_FIELD_COUNTRY, [
57
-			'value' => &$this->country,
58
-			'validate' => null,
59
-			'type' => 'VARCHAR',
60
-			'length' => 1024,
61
-			'properties' => null
62
-		]);
63
-
64
-		$this->address = null;
65
-		$this->zipcode = null;
66
-		$this->city = null;
67
-		$this->country = null;
68
-	}
69
-
70
-	/**
71
-	 * @return string
72
-	 */
73
-	public function getAddress()
74
-	{
75
-		return $this->address;
76
-	}
14
+    /** @var string the address line */
15
+    protected $address;
16
+
17
+    /** @var string the zipcode */
18
+    protected $zipcode;
19
+
20
+    /** @var string the city */
21
+    protected $city;
22
+
23
+    /** @var string the country */
24
+    protected $country;
25
+
26
+    /**
27
+     * Registers the Address trait on the including class
28
+     * @return void
29
+     */
30
+    protected function initAddress() 
31
+    {
32
+        $this->extendTableDefinition(TRAIT_ADDRESS_FIELD_ADDRESS, [
33
+            'value' => &$this->address,
34
+            'validate' => null,
35
+            'type' => 'VARCHAR',
36
+            'length' => 1024,
37
+            'properties' => null
38
+        ]);
39
+
40
+        $this->extendTableDefinition(TRAIT_ADDRESS_FIELD_ZIPCODE, [
41
+            'value' => &$this->zipcode,
42
+            'validate' => null,
43
+            'type' => 'VARCHAR',
44
+            'length' => 1024,
45
+            'properties' => null
46
+        ]);
47
+
48
+        $this->extendTableDefinition(TRAIT_ADDRESS_FIELD_CITY, [
49
+            'value' => &$this->city,
50
+            'validate' => null,
51
+            'type' => 'VARCHAR',
52
+            'length' => 1024,
53
+            'properties' => null
54
+        ]);
55
+
56
+        $this->extendTableDefinition(TRAIT_ADDRESS_FIELD_COUNTRY, [
57
+            'value' => &$this->country,
58
+            'validate' => null,
59
+            'type' => 'VARCHAR',
60
+            'length' => 1024,
61
+            'properties' => null
62
+        ]);
63
+
64
+        $this->address = null;
65
+        $this->zipcode = null;
66
+        $this->city = null;
67
+        $this->country = null;
68
+    }
69
+
70
+    /**
71
+     * @return string
72
+     */
73
+    public function getAddress()
74
+    {
75
+        return $this->address;
76
+    }
77 77
 	
78
-	/**
79
-	 * @param string $address
80
-	 */
81
-	public function setAddress($address)
82
-	{
83
-		$this->address = $address;
84
-	}
85
-
86
-	/**
87
-	 * @return string
88
-	 */
89
-	public function getZipcode()
90
-	{
91
-		return $this->zipcode;
92
-	}
78
+    /**
79
+     * @param string $address
80
+     */
81
+    public function setAddress($address)
82
+    {
83
+        $this->address = $address;
84
+    }
85
+
86
+    /**
87
+     * @return string
88
+     */
89
+    public function getZipcode()
90
+    {
91
+        return $this->zipcode;
92
+    }
93 93
 	
94
-	/**
95
-	 * @param string $zipcode
96
-	 */
97
-	public function setZipcode($zipcode)
98
-	{
99
-		$this->zipcode = $zipcode;
100
-	}
101
-
102
-	/**
103
-	 * @return string
104
-	 */
105
-	public function getCity()
106
-	{
107
-		return $this->city;
108
-	}
94
+    /**
95
+     * @param string $zipcode
96
+     */
97
+    public function setZipcode($zipcode)
98
+    {
99
+        $this->zipcode = $zipcode;
100
+    }
101
+
102
+    /**
103
+     * @return string
104
+     */
105
+    public function getCity()
106
+    {
107
+        return $this->city;
108
+    }
109 109
 	
110
-	/**
111
-	 * @param string $city
112
-	 */
113
-	public function setCity($city)
114
-	{
115
-		$this->city = $city;
116
-	}
117
-
118
-	/**
119
-	 * @return string
120
-	 */
121
-	public function getCountry()
122
-	{
123
-		return $this->country;
124
-	}
110
+    /**
111
+     * @param string $city
112
+     */
113
+    public function setCity($city)
114
+    {
115
+        $this->city = $city;
116
+    }
117
+
118
+    /**
119
+     * @return string
120
+     */
121
+    public function getCountry()
122
+    {
123
+        return $this->country;
124
+    }
125 125
 	
126
-	/**
127
-	 * @param string $country
128
-	 */
129
-	public function setCountry($country)
130
-	{
131
-		$this->country = $country;
132
-	}
133
-
134
-	/**
135
-	 * @return void
136
-	 */
137
-	abstract protected function extendTableDefinition($columnName, $definition);
126
+    /**
127
+     * @param string $country
128
+     */
129
+    public function setCountry($country)
130
+    {
131
+        $this->country = $country;
132
+    }
133
+
134
+    /**
135
+     * @return void
136
+     */
137
+    abstract protected function extendTableDefinition($columnName, $definition);
138 138
 	
139
-	/**
140
-	 * @return void
141
-	 */
142
-	abstract protected function registerSearchHook($columnName, $fn);
143
-
144
-	/**
145
-	 * @return void
146
-	 */
147
-	abstract protected function registerDeleteHook($columnName, $fn);
148
-
149
-	/**
150
-	 * @return void
151
-	 */
152
-	abstract protected function registerUpdateHook($columnName, $fn);
153
-
154
-	/**
155
-	 * @return void
156
-	 */
157
-	abstract protected function registerReadHook($columnName, $fn);
158
-
159
-	/**
160
-	 * @return void
161
-	 */
162
-	abstract protected function registerCreateHook($columnName, $fn);
139
+    /**
140
+     * @return void
141
+     */
142
+    abstract protected function registerSearchHook($columnName, $fn);
143
+
144
+    /**
145
+     * @return void
146
+     */
147
+    abstract protected function registerDeleteHook($columnName, $fn);
148
+
149
+    /**
150
+     * @return void
151
+     */
152
+    abstract protected function registerUpdateHook($columnName, $fn);
153
+
154
+    /**
155
+     * @return void
156
+     */
157
+    abstract protected function registerReadHook($columnName, $fn);
158
+
159
+    /**
160
+     * @return void
161
+     */
162
+    abstract protected function registerCreateHook($columnName, $fn);
163 163
 	
164 164
 }
165 165
\ No newline at end of file
Please login to merge, or discard this patch.
src/Traits/Password.php 1 patch
Indentation   +156 added lines, -156 removed lines patch added patch discarded remove patch
@@ -13,163 +13,163 @@
 block discarded – undo
13 13
 
14 14
 trait Password
15 15
 {
16
-	/** @var string The password hash. */
17
-	protected $password;
18
-
19
-	/** @var string|null The password reset token. */
20
-	protected $passwordResetToken;
21
-
22
-	/**
23
-	 * this method is required to be called in the constructor for each class that uses this trait. 
24
-	 * It adds the fields necessary for the passwords struct to the table definition
25
-	 */
26
-	protected function initPassword()
27
-	{
28
-		$this->extendTableDefinition(TRAIT_PASSWORD_FIELD_PASSWORD, [
29
-			'value' => &$this->password,
30
-			'validate' => [$this, 'validatePassword'],
31
-			'type' => 'VARCHAR',
32
-			'length' => 1024,
33
-			'properties' => null
34
-		]);
35
-
36
-		$this->extendTableDefinition(TRAIT_PASSWORD_FIELD_PASSWORD_RESET_TOKEN, [
37
-			'value' => &$this->passwordResetToken,
38
-			'validate' => null,
39
-			'default' => 0,
40
-			'type' => 'VARCHAR',
41
-			'length' => 1024
42
-		]);
43
-	}
44
-
45
-
46
-	/**
47
-	 * Returns whether the users password has been set
48
-	 * @return boolean true if the user has a password
49
-	 */
50
-	public function hasPasswordBeenSet()
51
-	{
52
-		return $this->password !== null;
53
-	}
54
-
55
-	/**
56
-	 * Returns true if the credentials are correct.
57
-	 *
58
-	 * @param string $password
59
-	 * @return boolean true if the credentials are correct
60
-	 */
61
-	public function isPassword($password)
62
-	{ 
63
-		if (!$this->hasPasswordBeenSet())
64
-		{
65
-			throw new ActiveRecordTraitException("Password field has not been set");
66
-		}
67
-
68
-		if (!password_verify($password, $this->password)) {
69
-			return false;
70
-		}
71
-
72
-		if (password_needs_rehash($this->password, TRAIT_PASSWORD_ENCRYPTION, ['cost' => TRAIT_PASSWORD_STRENTH])) {
73
-			$this->setPassword($password)->sync();
74
-		}
75
-
76
-		return true;
77
-	}
78
-
79
-	public function validatePassword($password) {
80
-		if (strlen($password) < TRAIT_PASSWORD_MIN_LENGTH) {
81
-			$message = sprintf('\'Password\' must be atleast %s characters long. %s characters provied.', TRAIT_PASSWORD_MIN_LENGTH, strlen($password));
82
-			return [false, $message];
83
-		}
84
-		return [true, ''];
85
-	}
86
-
87
-	/**
88
-	 * Set the password.
89
-	 *
90
-	 * @param string $password
91
-	 * @return $this
92
-	 * @throws \Exception
93
-	 */
94
-	public function setPassword($password)
95
-	{
96
-		[$status, $error] = $this->validatePassword($password);
97
-		if (!$status) {
98
-			throw new ActiveRecordTraitException($error);
99
-		}
100
-
101
-		$passwordHash = \password_hash($password, TRAIT_PASSWORD_ENCRYPTION, ['cost' => TRAIT_PASSWORD_STRENTH]);
102
-
103
-		if ($passwordHash === false) {
104
-			throw new ActiveRecordTraitException('\'Password\' hash failed.');
105
-		}
106
-
107
-		$this->password = $passwordHash;
108
-
109
-		return $this;
110
-	}
111
-
112
-	/**
113
-	 * @return string The Hash of the password
114
-	 */
115
-	public function getPasswordHash()
116
-	{
117
-		return $this->password;
118
-	}
119
-
120
-	/**
121
-	 * Returns the currently set password token for the entity, or null if not set
122
-	 * @return string|null The password reset token
123
-	 */
124
-	public function getPasswordResetToken()
125
-	{
126
-		return $this->passwordResetToken;
127
-	}
128
-
129
-	/**
130
-	 * Generates a new password reset token for the user
131
-	 */
132
-	public function generatePasswordResetToken()
133
-	{
134
-		$this->passwordResetToken = md5(uniqid(mt_rand(), true));
135
-	}
136
-
137
-	/**
138
-	 * Clears the current password reset token
139
-	 */
140
-	public function clearPasswordResetToken()
141
-	{
142
-		$this->passwordResetToken = null;
143
-	}
16
+    /** @var string The password hash. */
17
+    protected $password;
18
+
19
+    /** @var string|null The password reset token. */
20
+    protected $passwordResetToken;
21
+
22
+    /**
23
+     * this method is required to be called in the constructor for each class that uses this trait. 
24
+     * It adds the fields necessary for the passwords struct to the table definition
25
+     */
26
+    protected function initPassword()
27
+    {
28
+        $this->extendTableDefinition(TRAIT_PASSWORD_FIELD_PASSWORD, [
29
+            'value' => &$this->password,
30
+            'validate' => [$this, 'validatePassword'],
31
+            'type' => 'VARCHAR',
32
+            'length' => 1024,
33
+            'properties' => null
34
+        ]);
35
+
36
+        $this->extendTableDefinition(TRAIT_PASSWORD_FIELD_PASSWORD_RESET_TOKEN, [
37
+            'value' => &$this->passwordResetToken,
38
+            'validate' => null,
39
+            'default' => 0,
40
+            'type' => 'VARCHAR',
41
+            'length' => 1024
42
+        ]);
43
+    }
44
+
45
+
46
+    /**
47
+     * Returns whether the users password has been set
48
+     * @return boolean true if the user has a password
49
+     */
50
+    public function hasPasswordBeenSet()
51
+    {
52
+        return $this->password !== null;
53
+    }
54
+
55
+    /**
56
+     * Returns true if the credentials are correct.
57
+     *
58
+     * @param string $password
59
+     * @return boolean true if the credentials are correct
60
+     */
61
+    public function isPassword($password)
62
+    { 
63
+        if (!$this->hasPasswordBeenSet())
64
+        {
65
+            throw new ActiveRecordTraitException("Password field has not been set");
66
+        }
67
+
68
+        if (!password_verify($password, $this->password)) {
69
+            return false;
70
+        }
71
+
72
+        if (password_needs_rehash($this->password, TRAIT_PASSWORD_ENCRYPTION, ['cost' => TRAIT_PASSWORD_STRENTH])) {
73
+            $this->setPassword($password)->sync();
74
+        }
75
+
76
+        return true;
77
+    }
78
+
79
+    public function validatePassword($password) {
80
+        if (strlen($password) < TRAIT_PASSWORD_MIN_LENGTH) {
81
+            $message = sprintf('\'Password\' must be atleast %s characters long. %s characters provied.', TRAIT_PASSWORD_MIN_LENGTH, strlen($password));
82
+            return [false, $message];
83
+        }
84
+        return [true, ''];
85
+    }
86
+
87
+    /**
88
+     * Set the password.
89
+     *
90
+     * @param string $password
91
+     * @return $this
92
+     * @throws \Exception
93
+     */
94
+    public function setPassword($password)
95
+    {
96
+        [$status, $error] = $this->validatePassword($password);
97
+        if (!$status) {
98
+            throw new ActiveRecordTraitException($error);
99
+        }
100
+
101
+        $passwordHash = \password_hash($password, TRAIT_PASSWORD_ENCRYPTION, ['cost' => TRAIT_PASSWORD_STRENTH]);
102
+
103
+        if ($passwordHash === false) {
104
+            throw new ActiveRecordTraitException('\'Password\' hash failed.');
105
+        }
106
+
107
+        $this->password = $passwordHash;
108
+
109
+        return $this;
110
+    }
111
+
112
+    /**
113
+     * @return string The Hash of the password
114
+     */
115
+    public function getPasswordHash()
116
+    {
117
+        return $this->password;
118
+    }
119
+
120
+    /**
121
+     * Returns the currently set password token for the entity, or null if not set
122
+     * @return string|null The password reset token
123
+     */
124
+    public function getPasswordResetToken()
125
+    {
126
+        return $this->passwordResetToken;
127
+    }
128
+
129
+    /**
130
+     * Generates a new password reset token for the user
131
+     */
132
+    public function generatePasswordResetToken()
133
+    {
134
+        $this->passwordResetToken = md5(uniqid(mt_rand(), true));
135
+    }
136
+
137
+    /**
138
+     * Clears the current password reset token
139
+     */
140
+    public function clearPasswordResetToken()
141
+    {
142
+        $this->passwordResetToken = null;
143
+    }
144 144
 	
145
-	/**
146
-	 * @return void
147
-	 */
148
-	abstract protected function extendTableDefinition($columnName, $definition);
145
+    /**
146
+     * @return void
147
+     */
148
+    abstract protected function extendTableDefinition($columnName, $definition);
149 149
 	
150
-	/**
151
-	 * @return void
152
-	 */
153
-	abstract protected function registerSearchHook($columnName, $fn);
154
-
155
-	/**
156
-	 * @return void
157
-	 */
158
-	abstract protected function registerDeleteHook($columnName, $fn);
159
-
160
-	/**
161
-	 * @return void
162
-	 */
163
-	abstract protected function registerUpdateHook($columnName, $fn);
164
-
165
-	/**
166
-	 * @return void
167
-	 */
168
-	abstract protected function registerReadHook($columnName, $fn);
169
-
170
-	/**
171
-	 * @return void
172
-	 */
173
-	abstract protected function registerCreateHook($columnName, $fn);
150
+    /**
151
+     * @return void
152
+     */
153
+    abstract protected function registerSearchHook($columnName, $fn);
154
+
155
+    /**
156
+     * @return void
157
+     */
158
+    abstract protected function registerDeleteHook($columnName, $fn);
159
+
160
+    /**
161
+     * @return void
162
+     */
163
+    abstract protected function registerUpdateHook($columnName, $fn);
164
+
165
+    /**
166
+     * @return void
167
+     */
168
+    abstract protected function registerReadHook($columnName, $fn);
169
+
170
+    /**
171
+     * @return void
172
+     */
173
+    abstract protected function registerCreateHook($columnName, $fn);
174 174
 
175 175
 }
176 176
\ No newline at end of file
Please login to merge, or discard this patch.
src/ActiveRecordQuery.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -57,7 +57,7 @@
 block discarded – undo
57 57
 		} else if (count($clauses) >= 2)
58 58
 		{
59 59
 			$rest = array_slice($clauses, 1);
60
-			$this->query->where(Query::And($clauses[0], ...$rest));
60
+			$this->query->where(Query:: And ($clauses[0], ...$rest));
61 61
 		}
62 62
 
63 63
 		$this->query->select();
Please login to merge, or discard this patch.
Indentation   +181 added lines, -181 removed lines patch added patch discarded remove patch
@@ -21,190 +21,190 @@
 block discarded – undo
21 21
 class ActiveRecordQuery implements \IteratorAggregate
22 22
 {
23 23
 
24
-	private $clauses = [];
24
+    private $clauses = [];
25 25
 
26
-	private $query;
26
+    private $query;
27 27
 
28
-	private $results;
28
+    private $results;
29 29
 
30
-	private $table;
30
+    private $table;
31 31
 
32
-	private $type;
32
+    private $type;
33 33
 	
34
-	private $whereExpression = null;
35
-
36
-	/**
37
-	 * Constructs a new Active Record Query
38
-	 */
39
-	public function __construct(AbstractActiveRecord $instance, $table, Array $additionalWhereClauses)
40
-	{
41
-		$this->table = $table;
42
-		$this->query = new Query($instance->getPdo(), $table);
43
-		$this->type = $instance;
44
-		$this->clauses = $additionalWhereClauses;
45
-		$this->results = null;
46
-	}
47
-
48
-	/**
49
-	 * Executes the query
50
-	 */
51
-	private function execute()
52
-	{
53
-		$clauses = $this->clauses;
54
-
55
-		// Optionally add user concatenated where expression
56
-		if ($this->whereExpression !== null)
57
-		{
58
-			$clauses[] = $this->whereExpression;
59
-		}
60
-
61
-		// Construct where clause
62
-		if (count($clauses) == 1)
63
-		{
64
-			$this->query->where($clauses[0]);
65
-		} else if (count($clauses) >= 2)
66
-		{
67
-			$rest = array_slice($clauses, 1);
68
-			$this->query->where(Query::And($clauses[0], ...$rest));
69
-		}
70
-
71
-		$this->query->select();
72
-
73
-		$this->results = $this->query->execute();
74
-
75
-		return $this;
76
-	}
77
-
78
-	/**
79
-	 * Returns an iterator for the result set
80
-	 * @return ArrayIterator
81
-	 */
82
-	public function getIterator()
83
-	{
84
-		return new \ArrayIterator($this->fetchAll());
85
-	}
86
-
87
-	/**
88
-	 * returns the result set of ActiveRecord instances for this query
89
-	 * @return Array
90
-	 */
91
-	public function fetchAll()
92
-	{
93
-		try {
94
-			if ($this->results === null) {
95
-				$this->execute();	
96
-			}
97
-
98
-			$entries = $this->results->fetchAll();
99
-			if ($entries === false) {
100
-				throw new ActiveRecordException(sprintf('Can not search non-existent entries from the `%s` table.', $this->table));
101
-			}
102
-
103
-			$typedResults = [];
104
-
105
-			foreach ($entries as $entry) {
106
-				$typedEntry = $this->type->newInstance();
107
-				$typedEntry->fill($entry);
108
-				$typedResults[] = $typedEntry;
109
-			}
110
-
111
-			return $typedResults;
112
-		} catch (\PDOException $e) {
113
-			throw new ActiveRecordException($e->getMessage(), 0, $e);
114
-		}
115
-	}
116
-
117
-	/**
118
-	 * Fetch one record from the database
119
-	 * @return AbstractActiveRecord 
120
-	 */
121
-	public function fetch()
122
-	{
123
-		try {
124
-			if ($this->results === null) 
125
-			{
126
-				$this->execute();
127
-			}
128
-
129
-			$typedResult = $this->type->newInstance();
130
-
131
-			$entry = $this->results->fetch();
132
-			if ($entry === false) {
133
-				throw new ActiveRecordException(sprintf('Can not search one non-existent entry from the `%s` table.', $this->table));
134
-			}
135
-
136
-			$typedResult->fill($entry);
137
-
138
-			return $typedResult;
139
-		} catch (\PDOException $e) {
140
-			throw new ActiveRecordException($e->getMessage(), 0, $e);
141
-		}
142
-	}
143
-
144
-
145
-	/**
146
-	 * Set the where condition
147
-	 *
148
-	 * @param QueryExpression $expression the query expression
149
-	 * @return $this
150
-	 * @see https://en.wikipedia.org/wiki/SQL#Operators
151
-	 * @see https://en.wikipedia.org/wiki/Where_(SQL)
152
-	 */
153
-	public function where(QueryExpression $expression)
154
-	{
155
-		$this->whereExpression = $expression;
156
-		return $this;
157
-	}
158
-
159
-	/**
160
-	 * Set an additional group by.
161
-	 *
162
-	 * @param string $column
163
-	 * @return $this
164
-	 * @see https://en.wikipedia.org/wiki/SQL#Queries
165
-	 */
166
-	public function groupBy($column)
167
-	{
168
-		$this->query->groupBy($column);
169
-		return $this;
170
-	}
171
-
172
-	/**
173
-	 * Set an additional order condition.
174
-	 *
175
-	 * @param string $column
176
-	 * @param string|null $order
177
-	 * @return $this
178
-	 * @see https://en.wikipedia.org/wiki/SQL#Queries
179
-	 * @see https://en.wikipedia.org/wiki/Order_by
180
-	 */
181
-	public function orderBy($column, $order = null)
182
-	{
183
-		$this->query->orderBy($column, $order);	
184
-		return $this;
185
-	}
186
-
187
-	/**
188
-	 * Set the limit.
189
-	 *
190
-	 * @param mixed $limit
191
-	 * @return $this
192
-	 */
193
-	public function limit($limit)
194
-	{
195
-		$this->query->limit($limit);
196
-		return $this;
197
-	}
198
-
199
-	/**
200
-	 * Set the offset.
201
-	 *
202
-	 * @param mixed $offset
203
- 	 * @return $this
204
-	 */
205
-	public function offset($offset)
206
-	{
207
-		$this->query->offset($offset);
208
-		return $this;
209
-	}
34
+    private $whereExpression = null;
35
+
36
+    /**
37
+     * Constructs a new Active Record Query
38
+     */
39
+    public function __construct(AbstractActiveRecord $instance, $table, Array $additionalWhereClauses)
40
+    {
41
+        $this->table = $table;
42
+        $this->query = new Query($instance->getPdo(), $table);
43
+        $this->type = $instance;
44
+        $this->clauses = $additionalWhereClauses;
45
+        $this->results = null;
46
+    }
47
+
48
+    /**
49
+     * Executes the query
50
+     */
51
+    private function execute()
52
+    {
53
+        $clauses = $this->clauses;
54
+
55
+        // Optionally add user concatenated where expression
56
+        if ($this->whereExpression !== null)
57
+        {
58
+            $clauses[] = $this->whereExpression;
59
+        }
60
+
61
+        // Construct where clause
62
+        if (count($clauses) == 1)
63
+        {
64
+            $this->query->where($clauses[0]);
65
+        } else if (count($clauses) >= 2)
66
+        {
67
+            $rest = array_slice($clauses, 1);
68
+            $this->query->where(Query::And($clauses[0], ...$rest));
69
+        }
70
+
71
+        $this->query->select();
72
+
73
+        $this->results = $this->query->execute();
74
+
75
+        return $this;
76
+    }
77
+
78
+    /**
79
+     * Returns an iterator for the result set
80
+     * @return ArrayIterator
81
+     */
82
+    public function getIterator()
83
+    {
84
+        return new \ArrayIterator($this->fetchAll());
85
+    }
86
+
87
+    /**
88
+     * returns the result set of ActiveRecord instances for this query
89
+     * @return Array
90
+     */
91
+    public function fetchAll()
92
+    {
93
+        try {
94
+            if ($this->results === null) {
95
+                $this->execute();	
96
+            }
97
+
98
+            $entries = $this->results->fetchAll();
99
+            if ($entries === false) {
100
+                throw new ActiveRecordException(sprintf('Can not search non-existent entries from the `%s` table.', $this->table));
101
+            }
102
+
103
+            $typedResults = [];
104
+
105
+            foreach ($entries as $entry) {
106
+                $typedEntry = $this->type->newInstance();
107
+                $typedEntry->fill($entry);
108
+                $typedResults[] = $typedEntry;
109
+            }
110
+
111
+            return $typedResults;
112
+        } catch (\PDOException $e) {
113
+            throw new ActiveRecordException($e->getMessage(), 0, $e);
114
+        }
115
+    }
116
+
117
+    /**
118
+     * Fetch one record from the database
119
+     * @return AbstractActiveRecord 
120
+     */
121
+    public function fetch()
122
+    {
123
+        try {
124
+            if ($this->results === null) 
125
+            {
126
+                $this->execute();
127
+            }
128
+
129
+            $typedResult = $this->type->newInstance();
130
+
131
+            $entry = $this->results->fetch();
132
+            if ($entry === false) {
133
+                throw new ActiveRecordException(sprintf('Can not search one non-existent entry from the `%s` table.', $this->table));
134
+            }
135
+
136
+            $typedResult->fill($entry);
137
+
138
+            return $typedResult;
139
+        } catch (\PDOException $e) {
140
+            throw new ActiveRecordException($e->getMessage(), 0, $e);
141
+        }
142
+    }
143
+
144
+
145
+    /**
146
+     * Set the where condition
147
+     *
148
+     * @param QueryExpression $expression the query expression
149
+     * @return $this
150
+     * @see https://en.wikipedia.org/wiki/SQL#Operators
151
+     * @see https://en.wikipedia.org/wiki/Where_(SQL)
152
+     */
153
+    public function where(QueryExpression $expression)
154
+    {
155
+        $this->whereExpression = $expression;
156
+        return $this;
157
+    }
158
+
159
+    /**
160
+     * Set an additional group by.
161
+     *
162
+     * @param string $column
163
+     * @return $this
164
+     * @see https://en.wikipedia.org/wiki/SQL#Queries
165
+     */
166
+    public function groupBy($column)
167
+    {
168
+        $this->query->groupBy($column);
169
+        return $this;
170
+    }
171
+
172
+    /**
173
+     * Set an additional order condition.
174
+     *
175
+     * @param string $column
176
+     * @param string|null $order
177
+     * @return $this
178
+     * @see https://en.wikipedia.org/wiki/SQL#Queries
179
+     * @see https://en.wikipedia.org/wiki/Order_by
180
+     */
181
+    public function orderBy($column, $order = null)
182
+    {
183
+        $this->query->orderBy($column, $order);	
184
+        return $this;
185
+    }
186
+
187
+    /**
188
+     * Set the limit.
189
+     *
190
+     * @param mixed $limit
191
+     * @return $this
192
+     */
193
+    public function limit($limit)
194
+    {
195
+        $this->query->limit($limit);
196
+        return $this;
197
+    }
198
+
199
+    /**
200
+     * Set the offset.
201
+     *
202
+     * @param mixed $offset
203
+     * @return $this
204
+     */
205
+    public function offset($offset)
206
+    {
207
+        $this->query->offset($offset);
208
+        return $this;
209
+    }
210 210
 }
Please login to merge, or discard this patch.
src/ActiveRecordInterface.php 1 patch
Indentation   +60 added lines, -60 removed lines patch added patch discarded remove patch
@@ -19,72 +19,72 @@
 block discarded – undo
19 19
 interface ActiveRecordInterface
20 20
 {
21 21
 
22
-	public function __construct(\PDO $pdo);
22
+    public function __construct(\PDO $pdo);
23 23
 	
24
-	/**
25
-	 * Returns this active record after creating an entry with the records attributes.
26
-	 *
27
-	 * @return $this
28
-	 * @throws ActiveRecordException on failure.
29
-	 */
30
-	public function create();
24
+    /**
25
+     * Returns this active record after creating an entry with the records attributes.
26
+     *
27
+     * @return $this
28
+     * @throws ActiveRecordException on failure.
29
+     */
30
+    public function create();
31 31
 
32
-	/**
33
-	 * Returns this active record after reading the attributes from the entry with the given identifier.
34
-	 *
35
-	 * @param mixed $id
36
-	 * @return $this
37
-	 * @throws ActiveRecordException on failure.
38
-	 */
39
-	public function read($id);
32
+    /**
33
+     * Returns this active record after reading the attributes from the entry with the given identifier.
34
+     *
35
+     * @param mixed $id
36
+     * @return $this
37
+     * @throws ActiveRecordException on failure.
38
+     */
39
+    public function read($id);
40 40
 
41
-	/**
42
-	 * Returns this active record after updating the attributes to the corresponding entry.
43
-	 *
44
-	 * @return $this
45
-	 * @throws ActiveRecordException on failure.
46
-	 */
47
-	public function update();
41
+    /**
42
+     * Returns this active record after updating the attributes to the corresponding entry.
43
+     *
44
+     * @return $this
45
+     * @throws ActiveRecordException on failure.
46
+     */
47
+    public function update();
48 48
 
49
-	/**
50
-	 * Returns this record after deleting the corresponding entry.
51
-	 *
52
-	 * @return $this
53
-	 * @throws ActiveRecordException on failure.
54
-	 */
55
-	public function delete();
49
+    /**
50
+     * Returns this record after deleting the corresponding entry.
51
+     *
52
+     * @return $this
53
+     * @throws ActiveRecordException on failure.
54
+     */
55
+    public function delete();
56 56
 
57
-	/**
58
-	 * Returns this record after synchronizing it with the corresponding entry.
59
-	 * A new entry is created if this active record does not have a corresponding entry.
60
-	 *
61
-	 * @return $this
62
-	 * @throws ActiveRecordException on failure.
63
-	 */
64
-	public function sync();
57
+    /**
58
+     * Returns this record after synchronizing it with the corresponding entry.
59
+     * A new entry is created if this active record does not have a corresponding entry.
60
+     *
61
+     * @return $this
62
+     * @throws ActiveRecordException on failure.
63
+     */
64
+    public function sync();
65 65
 
66
-	/**
67
-	 * Returns true if this active record has a corresponding entry.
68
-	 *
69
-	 * @return bool true if this active record has a corresponding entry.
70
-	 */
71
-	public function exists();
66
+    /**
67
+     * Returns true if this active record has a corresponding entry.
68
+     *
69
+     * @return bool true if this active record has a corresponding entry.
70
+     */
71
+    public function exists();
72 72
 
73
-	/**
74
-	 * Returns this record after filling it with the given attributes.
75
-	 *
76
-	 * @param array $attributes = []
77
-	 * @return $this
78
-	 * @throws ActiveRecordException on failure.
79
-	 */
80
-	public function fill(array $attributes);
73
+    /**
74
+     * Returns this record after filling it with the given attributes.
75
+     *
76
+     * @param array $attributes = []
77
+     * @return $this
78
+     * @throws ActiveRecordException on failure.
79
+     */
80
+    public function fill(array $attributes);
81 81
 
82
-	/**
83
-	 * Returns the records with the given where, order by, limit and offset clauses.
84
-	 *
85
-	 * @param array $excludedTraits
86
-	 * @return ActiveRecordQuery the query representing the current search.
87
-	 * @throws ActiveRecordException on failure.
88
-	 */
89
-	public function search(Array $excludedTraits);
82
+    /**
83
+     * Returns the records with the given where, order by, limit and offset clauses.
84
+     *
85
+     * @param array $excludedTraits
86
+     * @return ActiveRecordQuery the query representing the current search.
87
+     * @throws ActiveRecordException on failure.
88
+     */
89
+    public function search(Array $excludedTraits);
90 90
 }
Please login to merge, or discard this patch.
src/Traits/ManyToManyRelation.php 1 patch
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -8,115 +8,115 @@
 block discarded – undo
8 8
 
9 9
 Trait ManyToManyRelation
10 10
 {
11
-	// These variables are relevant for internal bookkeeping (constraint generation etc)
12
-
13
-	/** @var string The name of the left column of the relation. */
14
-	private $_leftColumnName;
15
-
16
-	/** @var string The name of the right column of the relation. */
17
-	private $_rightColumnName;
18
-
19
-	/** @var string The name of the left table of the relation. */
20
-	private $_leftEntityTable;
21
-
22
-	/** @var string The name of the right table of the relation. */
23
-	private $_rightEntityTable;
24
-
25
-	/** @var \PDO The PDO object. */
26
-	protected $pdo;
27
-	/**
28
-	 * Initializes the the ManyToManyRelation trait on the included object
29
-	 * 
30
-	 * @param AbstractActiveRecord $leftEntity The left entity of the relation
31
-	 * @param int $leftVariable The reference to the variable where the id for the left entity will be stored
32
-	 * @param AbstractActiveRecord $rightEntity The left entity of the relation
33
-	 * @param int $leftVariable The reference to the variable where the id for the right entity will be stored
34
-	 * @return void
35
-	 */
36
-	protected function initManyToManyRelation(AbstractActiveRecord $leftEntity, &$leftVariable, AbstractActiveRecord $rightEntity, &$rightVariable)
37
-	{
38
-		$this->_leftEntityTable = $leftEntity->getTableName();
39
-		$this->_rightEntityTable = $rightEntity->getTableName();
40
-
41
-		if (get_class($leftEntity) === get_class($rightEntity)) {
42
-			$this->_leftColumnName = sprintf("id_%s_left", $leftEntity->getTableName());
43
-			$this->_rightColumnName = sprintf("id_%s_right", $rightEntity->getTableName());
44
-		} else {
45
-			$this->_leftColumnName = sprintf("id_%s", $leftEntity->getTableName());
46
-			$this->_rightColumnName = sprintf("id_%s", $rightEntity->getTableName());
47
-		}
48
-
49
-		$this->extendTableDefinition($this->_leftColumnName, [
50
-			'value' => &$leftVariable,
51
-			'validate' => null,
52
-			'type' => AbstractActiveRecord::COLUMN_TYPE_ID,
53
-			'properties' => ColumnProperty::NOT_NULL
54
-		]);
55
-
56
-		$this->extendTableDefinition($this->_rightColumnName, [
57
-			'value' => &$rightVariable,
58
-			'validate' => null,
59
-			'type' => AbstractActiveRecord::COLUMN_TYPE_ID,
60
-			'properties' => ColumnProperty::NOT_NULL
61
-		]);
62
-	}
63
-
64
-	/**
65
-	 * Build the constraints for the many-to-many relation table
66
-	 * @return void
67
-	 */
68
-	public function createTableConstraints()
69
-	{
70
-		$childTable = $this->getTableName();
71
-
72
-		$leftParentTable = $this->_leftEntityTable;
73
-		$rightParentTable = $this->_rightEntityTable;
74
-
75
-		$leftConstraint = $this->buildConstraint($leftParentTable, 'id', $childTable, $this->_leftColumnName);
76
-		$rightConstraint = $this->buildConstraint($rightParentTable, 'id', $childTable, $this->_rightColumnName);
77
-
78
-		$this->pdo->query($leftConstraint);
79
-		$this->pdo->query($rightConstraint);
80
-	}
81
-
82
-	/**
83
-	 * @return void
84
-	 */	
85
-	abstract protected function getTableName();
86
-
87
-	/**
88
-	 * @return void
89
-	 */
90
-	abstract protected function buildConstraint($parentTable, $parentColumn, $childTable, $childColumn);
91
-
92
-	/**
93
-	 * @return void
94
-	 */
95
-	abstract protected function extendTableDefinition($columnName, $definition);
11
+    // These variables are relevant for internal bookkeeping (constraint generation etc)
12
+
13
+    /** @var string The name of the left column of the relation. */
14
+    private $_leftColumnName;
15
+
16
+    /** @var string The name of the right column of the relation. */
17
+    private $_rightColumnName;
18
+
19
+    /** @var string The name of the left table of the relation. */
20
+    private $_leftEntityTable;
21
+
22
+    /** @var string The name of the right table of the relation. */
23
+    private $_rightEntityTable;
24
+
25
+    /** @var \PDO The PDO object. */
26
+    protected $pdo;
27
+    /**
28
+     * Initializes the the ManyToManyRelation trait on the included object
29
+     * 
30
+     * @param AbstractActiveRecord $leftEntity The left entity of the relation
31
+     * @param int $leftVariable The reference to the variable where the id for the left entity will be stored
32
+     * @param AbstractActiveRecord $rightEntity The left entity of the relation
33
+     * @param int $leftVariable The reference to the variable where the id for the right entity will be stored
34
+     * @return void
35
+     */
36
+    protected function initManyToManyRelation(AbstractActiveRecord $leftEntity, &$leftVariable, AbstractActiveRecord $rightEntity, &$rightVariable)
37
+    {
38
+        $this->_leftEntityTable = $leftEntity->getTableName();
39
+        $this->_rightEntityTable = $rightEntity->getTableName();
40
+
41
+        if (get_class($leftEntity) === get_class($rightEntity)) {
42
+            $this->_leftColumnName = sprintf("id_%s_left", $leftEntity->getTableName());
43
+            $this->_rightColumnName = sprintf("id_%s_right", $rightEntity->getTableName());
44
+        } else {
45
+            $this->_leftColumnName = sprintf("id_%s", $leftEntity->getTableName());
46
+            $this->_rightColumnName = sprintf("id_%s", $rightEntity->getTableName());
47
+        }
48
+
49
+        $this->extendTableDefinition($this->_leftColumnName, [
50
+            'value' => &$leftVariable,
51
+            'validate' => null,
52
+            'type' => AbstractActiveRecord::COLUMN_TYPE_ID,
53
+            'properties' => ColumnProperty::NOT_NULL
54
+        ]);
55
+
56
+        $this->extendTableDefinition($this->_rightColumnName, [
57
+            'value' => &$rightVariable,
58
+            'validate' => null,
59
+            'type' => AbstractActiveRecord::COLUMN_TYPE_ID,
60
+            'properties' => ColumnProperty::NOT_NULL
61
+        ]);
62
+    }
63
+
64
+    /**
65
+     * Build the constraints for the many-to-many relation table
66
+     * @return void
67
+     */
68
+    public function createTableConstraints()
69
+    {
70
+        $childTable = $this->getTableName();
71
+
72
+        $leftParentTable = $this->_leftEntityTable;
73
+        $rightParentTable = $this->_rightEntityTable;
74
+
75
+        $leftConstraint = $this->buildConstraint($leftParentTable, 'id', $childTable, $this->_leftColumnName);
76
+        $rightConstraint = $this->buildConstraint($rightParentTable, 'id', $childTable, $this->_rightColumnName);
77
+
78
+        $this->pdo->query($leftConstraint);
79
+        $this->pdo->query($rightConstraint);
80
+    }
81
+
82
+    /**
83
+     * @return void
84
+     */	
85
+    abstract protected function getTableName();
86
+
87
+    /**
88
+     * @return void
89
+     */
90
+    abstract protected function buildConstraint($parentTable, $parentColumn, $childTable, $childColumn);
91
+
92
+    /**
93
+     * @return void
94
+     */
95
+    abstract protected function extendTableDefinition($columnName, $definition);
96 96
 	
97
-	/**
98
-	 * @return void
99
-	 */
100
-	abstract protected function registerSearchHook($columnName, $fn);
101
-
102
-	/**
103
-	 * @return void
104
-	 */
105
-	abstract protected function registerDeleteHook($columnName, $fn);
106
-
107
-	/**
108
-	 * @return void
109
-	 */
110
-	abstract protected function registerUpdateHook($columnName, $fn);
111
-
112
-	/**
113
-	 * @return void
114
-	 */
115
-	abstract protected function registerReadHook($columnName, $fn);
116
-
117
-	/**
118
-	 * @return void
119
-	 */
120
-	abstract protected function registerCreateHook($columnName, $fn);
97
+    /**
98
+     * @return void
99
+     */
100
+    abstract protected function registerSearchHook($columnName, $fn);
101
+
102
+    /**
103
+     * @return void
104
+     */
105
+    abstract protected function registerDeleteHook($columnName, $fn);
106
+
107
+    /**
108
+     * @return void
109
+     */
110
+    abstract protected function registerUpdateHook($columnName, $fn);
111
+
112
+    /**
113
+     * @return void
114
+     */
115
+    abstract protected function registerReadHook($columnName, $fn);
116
+
117
+    /**
118
+     * @return void
119
+     */
120
+    abstract protected function registerCreateHook($columnName, $fn);
121 121
 
122 122
 }
Please login to merge, or discard this patch.
src/Traits/AutoApi.php 1 patch
Indentation   +360 added lines, -360 removed lines patch added patch discarded remove patch
@@ -9,379 +9,379 @@
 block discarded – undo
9 9
 
10 10
 trait AutoApi
11 11
 {
12
-	/* =======================================================================
12
+    /* =======================================================================
13 13
 	 * ===================== Automatic API Support ===========================
14 14
 	 * ======================================================================= */
15 15
 
16
-	/** @var array A map of column name to functions that hook the insert function */
17
-	protected $registeredCreateHooks;
16
+    /** @var array A map of column name to functions that hook the insert function */
17
+    protected $registeredCreateHooks;
18 18
 
19
-	/** @var array A map of column name to functions that hook the read function */
20
-	protected $registeredReadHooks;
19
+    /** @var array A map of column name to functions that hook the read function */
20
+    protected $registeredReadHooks;
21 21
 
22
-	/** @var array A map of column name to functions that hook the update function */
23
-	protected $registeredUpdateHooks;
22
+    /** @var array A map of column name to functions that hook the update function */
23
+    protected $registeredUpdateHooks;
24 24
 
25
-	/** @var array A map of column name to functions that hook the update function */
26
-	protected $registeredDeleteHooks;	
25
+    /** @var array A map of column name to functions that hook the update function */
26
+    protected $registeredDeleteHooks;	
27 27
 
28
-	/** @var array A map of column name to functions that hook the search function */
29
-	protected $registeredSearchHooks;
28
+    /** @var array A map of column name to functions that hook the search function */
29
+    protected $registeredSearchHooks;
30 30
 
31
-	/** @var array A list of table column definitions */
32
-	protected $tableDefinition;
31
+    /** @var array A list of table column definitions */
32
+    protected $tableDefinition;
33 33
 
34 34
 
35
-	/**
36
-	 * @param Array $queryparams associative array of query params. Reserved options are
37
-	 *                             "search_order_by", "search_order_direction", "search_limit", "search_offset"
38
-	 *                             or column names corresponding to an instance of miBadger\Query\QueryExpression
39
-	 * @param Array $fieldWhitelist names of the columns that will appear in the output results
40
-	 */
41
-	public function apiSearch(Array $queryParams, Array $fieldWhitelist, ?QueryExpression $whereClause = null)
42
-	{
43
-		$query = $this->search();
35
+    /**
36
+     * @param Array $queryparams associative array of query params. Reserved options are
37
+     *                             "search_order_by", "search_order_direction", "search_limit", "search_offset"
38
+     *                             or column names corresponding to an instance of miBadger\Query\QueryExpression
39
+     * @param Array $fieldWhitelist names of the columns that will appear in the output results
40
+     */
41
+    public function apiSearch(Array $queryParams, Array $fieldWhitelist, ?QueryExpression $whereClause = null)
42
+    {
43
+        $query = $this->search();
44 44
 
45
-		// Build query
46
-		$orderColumn = $queryParams['search_order_by'] ?? null;
47
-		$orderDirection = $queryParams['search_order_direction'] ?? null;
48
-		if ($orderColumn !== null) {
49
-			$query->orderBy($orderColumn, $orderDirection);
50
-		}
45
+        // Build query
46
+        $orderColumn = $queryParams['search_order_by'] ?? null;
47
+        $orderDirection = $queryParams['search_order_direction'] ?? null;
48
+        if ($orderColumn !== null) {
49
+            $query->orderBy($orderColumn, $orderDirection);
50
+        }
51 51
 		
52
-		$limit = $queryParams['search_limit'] ?? null;
53
-		if ($limit !== null) {
54
-			$query->limit($limit);
55
-		}
56
-
57
-		$offset = $queryParams['search_offset'] ?? null;
58
-		if ($offset !== null) {
59
-			$query->offset($offset);
60
-		}
61
-
62
-		if ($whereClause !== null) {
63
-			$query->where($whereClause);
64
-		}
65
-
66
-		// Fetch results
67
-		$results = $query->fetchAll();
68
-
69
-		$resultsArray = [];
70
-		foreach ($results as $result) {
71
-			$resultsArray[] = $result->toArray($fieldWhitelist);
72
-		}
73
-
74
-		return $resultsArray;
75
-	}
76
-
77
-	public function toArray($fieldWhitelist)
78
-	{
79
-		$output = [];
80
-		foreach ($this->tableDefinition as $colName => $definition) {
81
-			if (in_array($colName, $fieldWhitelist)) {
82
-				$output[$colName] = $definition['value'];
83
-			}
84
-		}
85
-
86
-		return $output;
87
-	}
88
-
89
-	public function apiRead($id, Array $fieldWhitelist)
90
-	{
91
-		$this->read($id);
92
-		return $this->toArray($fieldWhitelist);
93
-	}
94
-
95
-	/* =============================================================
52
+        $limit = $queryParams['search_limit'] ?? null;
53
+        if ($limit !== null) {
54
+            $query->limit($limit);
55
+        }
56
+
57
+        $offset = $queryParams['search_offset'] ?? null;
58
+        if ($offset !== null) {
59
+            $query->offset($offset);
60
+        }
61
+
62
+        if ($whereClause !== null) {
63
+            $query->where($whereClause);
64
+        }
65
+
66
+        // Fetch results
67
+        $results = $query->fetchAll();
68
+
69
+        $resultsArray = [];
70
+        foreach ($results as $result) {
71
+            $resultsArray[] = $result->toArray($fieldWhitelist);
72
+        }
73
+
74
+        return $resultsArray;
75
+    }
76
+
77
+    public function toArray($fieldWhitelist)
78
+    {
79
+        $output = [];
80
+        foreach ($this->tableDefinition as $colName => $definition) {
81
+            if (in_array($colName, $fieldWhitelist)) {
82
+                $output[$colName] = $definition['value'];
83
+            }
84
+        }
85
+
86
+        return $output;
87
+    }
88
+
89
+    public function apiRead($id, Array $fieldWhitelist)
90
+    {
91
+        $this->read($id);
92
+        return $this->toArray($fieldWhitelist);
93
+    }
94
+
95
+    /* =============================================================
96 96
 	 * ===================== Constraint validation =================
97 97
 	 * ============================================================= */
98 98
 
99
-	/**
100
-	 * Copy all table variables between two instances
101
-	 */
102
-	public function syncInstanceFrom($from)
103
-	{
104
-		foreach ($this->tableDefinition as $colName => $definition) {
105
-			$this->tableDefinition[$colName]['value'] = $from->tableDefinition[$colName]['value'];
106
-		}
107
-	}
108
-
109
-	private function filterInputColumns($input, $whitelist)
110
-	{
111
-		$filteredInput = $input;
112
-		foreach ($input as $colName => $value) {
113
-			if (!in_array($colName, $whitelist)) {
114
-				unset($filteredInput[$colName]);
115
-			}
116
-		}
117
-		return $filteredInput;
118
-	}
119
-
120
-	private function validateExcessKeys($input)
121
-	{
122
-		$errors = [];
123
-		foreach ($input as $colName => $value) {
124
-			if (!array_key_exists($colName, $this->tableDefinition)) {
125
-				$errors[$colName] = "Unknown input field";
126
-				continue;
127
-			}
128
-		}
129
-		return $errors;
130
-	}
131
-
132
-	private function validateImmutableColumns($input)
133
-	{
134
-		$errors = [];
135
-		foreach ($this->tableDefinition as $colName => $definition) {
136
-			$property = $definition['properties'] ?? null;
137
-			if (array_key_exists($colName, $input)
138
-				&& $property & ColumnProperty::IMMUTABLE) {
139
-				$errors[$colName] = "Field cannot be changed";
140
-			}
141
-		}
142
-		return $errors;
143
-	}
144
-
145
-	/**
146
-	 * Checks whether input values are correct:
147
-	 * 1. Checks whether a value passes the validation function for that column
148
-	 * 2. Checks whether a value supplied to a relationship column is a valid value
149
-	 */
150
-	private function validateInputValues($input)
151
-	{
152
-		$errors = [];
153
-		foreach ($this->tableDefinition as $colName => $definition) {
154
-			// Validation check 1: If validate function is present
155
-			if (array_key_exists($colName, $input) 
156
-				&& is_callable($definition['validate'] ?? null)) {
157
-				$inputValue = $input[$colName];
158
-
159
-				// If validation function fails
160
-				[$status, $message] = $definition['validate']($inputValue);
161
-				if (!$status) {
162
-					$errors[$colName] = $message;
163
-				}	
164
-			}
165
-
166
-			// Validation check 2: If relation column, check whether entity exists
167
-			$properties = $definition['properties'] ?? null;
168
-			if (isset($definition['relation'])
169
-				&& ($properties & ColumnProperty::NOT_NULL)) {
170
-				$instance = clone $definition['relation'];
171
-				try {
172
-					$instance->read($input[$colName] ?? null);
173
-				} catch (ActiveRecordException $e) {
174
-					$errors[$colName] = "Entity for this value doesn't exist";
175
-				}
176
-			}
177
-		}
178
-		return $errors;
179
-	}
180
-
181
-	/**
182
-	 * This function is only used for API Update calls (direct getter/setter functions are unconstrained)
183
-	 * Determines whether there are required columns for which no data is provided
184
-	 */
185
-	private function validateMissingKeys($input)
186
-	{
187
-		$errors = [];
188
-
189
-		foreach ($this->tableDefinition as $colName => $colDefinition) {
190
-			$default = $colDefinition['default'] ?? null;
191
-			$properties = $colDefinition['properties'] ?? null;
192
-			$value = $colDefinition['value'];
193
-
194
-			// If nullable and default not set => null
195
-			// If nullable and default null => default (null)
196
-			// If nullable and default set => default (value)
197
-
198
-			// if not nullable and default not set => error
199
-			// if not nullable and default null => error
200
-			// if not nullable and default st => default (value)
201
-			// => if not nullable and default null and value not set (or null) => error message in this method
202
-			if ($properties & ColumnProperty::NOT_NULL
203
-				&& $default === null
204
-				&& !($properties & ColumnProperty::AUTO_INCREMENT)
205
-				&& (!array_key_exists($colName, $input) || $input[$colName] === null)
206
-				&& $value === null) {
207
-				$errors[$colName] = sprintf("The required field \"%s\" is missing", $colName);
208
-			}
209
-		}
210
-
211
-		return $errors;
212
-	}
213
-
214
-	/**
215
-	 * Copies the values for entries in the input with matching variable names in the record definition
216
-	 * @param Array $input The input data to be loaded into $this record
217
-	 */
218
-	private function loadData($input)
219
-	{
220
-		foreach ($this->tableDefinition as $colName => $definition) {
221
-			if (array_key_exists($colName, $input)) {
222
-				$definition['value'] = $input[$colName];
223
-			}
224
-		}
225
-	}
226
-
227
-	/**
228
-	 * @param Array $input Associative array of input values
229
-	 * @param Array $fieldWhitelist array of column names that are allowed to be filled by the input array 
230
-	 * @return Array Array containing the set of optional errors (associative array) and an optional array representation (associative)
231
-	 * 					of the modified data.
232
-	 */
233
-	public function apiCreate($input, Array $createWhitelist, Array $readWhitelist)
234
-	{
235
-		// Clone $this to new instance (for restoring if validation goes wrong)
236
-		$transaction = $this->newInstance();
237
-		$errors = [];
238
-
239
-		// Filter out all non-whitelisted input values
240
-		$input = $this->filterInputColumns($input, $createWhitelist);
241
-
242
-		// Validate excess keys
243
-		$errors += $transaction->validateExcessKeys($input);
244
-
245
-		// Validate input values (using validation function)
246
-		$errors += $transaction->validateInputValues($input);
247
-
248
-		// "Copy" data into transaction
249
-		$transaction->loadData($input);
250
-
251
-		// Run create hooks
252
-		foreach ($transaction->registeredCreateHooks as $colName => $fn) {
253
-			$fn();
254
-		}
255
-
256
-		// Validate missing keys
257
-		$errors += $transaction->validateMissingKeys($input);
258
-
259
-		// If no errors, commit the pending data
260
-		if (empty($errors)) {
261
-			$this->syncInstanceFrom($transaction);
262
-
263
-			// Insert default values for not-null fields
264
-			foreach ($this->tableDefinition as $colName => $colDef) {
265
-				if ($this->tableDefinition[$colName]['value'] === null
266
-					&& isset($this->tableDefinition[$colName]['properties'])
267
-					&& $this->tableDefinition[$colName]['properties'] && ColumnProperty::NOT_NULL > 0
268
-					&& isset($this->tableDefinition[$colName]['default'])) {
269
-					$this->tableDefinition[$colName]['value'] = $this->tableDefinition[$colName]['default'];
270
-				}
271
-			}
272
-
273
-			try {
274
-				(new Query($this->getPdo(), $this->getTableName()))
275
-					->insert($this->getActiveRecordColumns())
276
-					->execute();
277
-
278
-				$this->setId(intval($this->getPdo()->lastInsertId()));
279
-			} catch (\PDOException $e) {
280
-				// @TODO: Potentially filter and store mysql messages (where possible) in error messages
281
-				throw new ActiveRecordException($e->getMessage(), 0, $e);
282
-			}
283
-
284
-			return [null, $this->toArray($readWhitelist)];
285
-		} else {
286
-			return [$errors, null];
287
-		}
288
-	}
289
-
290
-	/**
291
-	 * @param Array $input Associative array of input values
292
-	 * @param Array $fieldWhitelist array of column names that are allowed to be filled by the input array 
293
-	 * @return Array Array containing the set of optional errors (associative array) and an optional array representation (associative)
294
-	 * 					of the modified data.
295
-	 */
296
-	public function apiUpdate($input, Array $updateWhitelist, Array $readWhitelist)
297
-	{
298
-		$transaction = $this->newInstance();
299
-		$transaction->syncInstanceFrom($this);
300
-		$errors = [];
301
-
302
-		// Filter out all non-whitelisted input values
303
-		$input = $this->filterInputColumns($input, $updateWhitelist);
304
-
305
-		// Check for excess keys
306
-		$errors += $transaction->validateExcessKeys($input);
307
-
308
-		// Check for immutable keys
309
-		$errors += $transaction->validateImmutableColumns($input);
310
-
311
-		// Validate input values (using validation function)
312
-		$errors += $transaction->validateInputValues($input);
313
-
314
-		// "Copy" data into transaction
315
-		$transaction->loadData($input);
316
-
317
-		// Run create hooks
318
-		foreach ($transaction->registeredUpdateHooks as $colName => $fn) {
319
-			$fn();
320
-		}
321
-
322
-		// Validate missing keys
323
-		$errors += $transaction->validateMissingKeys($input);
324
-
325
-		// Update database
326
-		if (empty($errors)) {
327
-			$this->syncInstanceFrom($transaction);
328
-
329
-			try {
330
-				(new Query($this->getPdo(), $this->getTableName()))
331
-					->update($this->getActiveRecordColumns())
332
-					->where(Query::Equal('id', $this->getId()))
333
-					->execute();
334
-			} catch (\PDOException $e) {
335
-				throw new ActiveRecordException($e->getMessage(), 0, $e);
336
-			}
337
-
338
-			return [null, $this->toArray($readWhitelist)];
339
-		} else {
340
-			return [$errors, null];
341
-		}
342
-	}
343
-
344
-	/**
345
-	 * Returns this active record after reading the attributes from the entry with the given identifier.
346
-	 *
347
-	 * @param mixed $id
348
-	 * @return $this
349
-	 * @throws ActiveRecordException on failure.
350
-	 */
351
-	abstract public function read($id);
352
-
353
-	/**
354
-	 * Returns the PDO.
355
-	 *
356
-	 * @return \PDO the PDO.
357
-	 */
358
-	abstract public function getPdo();
359
-
360
-	/**
361
-	 * Set the ID.
362
-	 *
363
-	 * @param int $id
364
-	 * @return $this
365
-	 */
366
-	abstract protected function setId($id);
367
-
368
-	/**
369
-	 * Returns the ID.
370
-	 *
371
-	 * @return null|int The ID.
372
-	 */
373
-	abstract protected function getId();
374
-
375
-	/**
376
-	 * Returns the active record table.
377
-	 *
378
-	 * @return string the active record table name.
379
-	 */
380
-	abstract protected function getTableName();
381
-
382
-	/**
383
-	 * Returns the name -> variable mapping for the table definition.
384
-	 * @return Array The mapping
385
-	 */
386
-	abstract protected function getActiveRecordColumns();
99
+    /**
100
+     * Copy all table variables between two instances
101
+     */
102
+    public function syncInstanceFrom($from)
103
+    {
104
+        foreach ($this->tableDefinition as $colName => $definition) {
105
+            $this->tableDefinition[$colName]['value'] = $from->tableDefinition[$colName]['value'];
106
+        }
107
+    }
108
+
109
+    private function filterInputColumns($input, $whitelist)
110
+    {
111
+        $filteredInput = $input;
112
+        foreach ($input as $colName => $value) {
113
+            if (!in_array($colName, $whitelist)) {
114
+                unset($filteredInput[$colName]);
115
+            }
116
+        }
117
+        return $filteredInput;
118
+    }
119
+
120
+    private function validateExcessKeys($input)
121
+    {
122
+        $errors = [];
123
+        foreach ($input as $colName => $value) {
124
+            if (!array_key_exists($colName, $this->tableDefinition)) {
125
+                $errors[$colName] = "Unknown input field";
126
+                continue;
127
+            }
128
+        }
129
+        return $errors;
130
+    }
131
+
132
+    private function validateImmutableColumns($input)
133
+    {
134
+        $errors = [];
135
+        foreach ($this->tableDefinition as $colName => $definition) {
136
+            $property = $definition['properties'] ?? null;
137
+            if (array_key_exists($colName, $input)
138
+                && $property & ColumnProperty::IMMUTABLE) {
139
+                $errors[$colName] = "Field cannot be changed";
140
+            }
141
+        }
142
+        return $errors;
143
+    }
144
+
145
+    /**
146
+     * Checks whether input values are correct:
147
+     * 1. Checks whether a value passes the validation function for that column
148
+     * 2. Checks whether a value supplied to a relationship column is a valid value
149
+     */
150
+    private function validateInputValues($input)
151
+    {
152
+        $errors = [];
153
+        foreach ($this->tableDefinition as $colName => $definition) {
154
+            // Validation check 1: If validate function is present
155
+            if (array_key_exists($colName, $input) 
156
+                && is_callable($definition['validate'] ?? null)) {
157
+                $inputValue = $input[$colName];
158
+
159
+                // If validation function fails
160
+                [$status, $message] = $definition['validate']($inputValue);
161
+                if (!$status) {
162
+                    $errors[$colName] = $message;
163
+                }	
164
+            }
165
+
166
+            // Validation check 2: If relation column, check whether entity exists
167
+            $properties = $definition['properties'] ?? null;
168
+            if (isset($definition['relation'])
169
+                && ($properties & ColumnProperty::NOT_NULL)) {
170
+                $instance = clone $definition['relation'];
171
+                try {
172
+                    $instance->read($input[$colName] ?? null);
173
+                } catch (ActiveRecordException $e) {
174
+                    $errors[$colName] = "Entity for this value doesn't exist";
175
+                }
176
+            }
177
+        }
178
+        return $errors;
179
+    }
180
+
181
+    /**
182
+     * This function is only used for API Update calls (direct getter/setter functions are unconstrained)
183
+     * Determines whether there are required columns for which no data is provided
184
+     */
185
+    private function validateMissingKeys($input)
186
+    {
187
+        $errors = [];
188
+
189
+        foreach ($this->tableDefinition as $colName => $colDefinition) {
190
+            $default = $colDefinition['default'] ?? null;
191
+            $properties = $colDefinition['properties'] ?? null;
192
+            $value = $colDefinition['value'];
193
+
194
+            // If nullable and default not set => null
195
+            // If nullable and default null => default (null)
196
+            // If nullable and default set => default (value)
197
+
198
+            // if not nullable and default not set => error
199
+            // if not nullable and default null => error
200
+            // if not nullable and default st => default (value)
201
+            // => if not nullable and default null and value not set (or null) => error message in this method
202
+            if ($properties & ColumnProperty::NOT_NULL
203
+                && $default === null
204
+                && !($properties & ColumnProperty::AUTO_INCREMENT)
205
+                && (!array_key_exists($colName, $input) || $input[$colName] === null)
206
+                && $value === null) {
207
+                $errors[$colName] = sprintf("The required field \"%s\" is missing", $colName);
208
+            }
209
+        }
210
+
211
+        return $errors;
212
+    }
213
+
214
+    /**
215
+     * Copies the values for entries in the input with matching variable names in the record definition
216
+     * @param Array $input The input data to be loaded into $this record
217
+     */
218
+    private function loadData($input)
219
+    {
220
+        foreach ($this->tableDefinition as $colName => $definition) {
221
+            if (array_key_exists($colName, $input)) {
222
+                $definition['value'] = $input[$colName];
223
+            }
224
+        }
225
+    }
226
+
227
+    /**
228
+     * @param Array $input Associative array of input values
229
+     * @param Array $fieldWhitelist array of column names that are allowed to be filled by the input array 
230
+     * @return Array Array containing the set of optional errors (associative array) and an optional array representation (associative)
231
+     * 					of the modified data.
232
+     */
233
+    public function apiCreate($input, Array $createWhitelist, Array $readWhitelist)
234
+    {
235
+        // Clone $this to new instance (for restoring if validation goes wrong)
236
+        $transaction = $this->newInstance();
237
+        $errors = [];
238
+
239
+        // Filter out all non-whitelisted input values
240
+        $input = $this->filterInputColumns($input, $createWhitelist);
241
+
242
+        // Validate excess keys
243
+        $errors += $transaction->validateExcessKeys($input);
244
+
245
+        // Validate input values (using validation function)
246
+        $errors += $transaction->validateInputValues($input);
247
+
248
+        // "Copy" data into transaction
249
+        $transaction->loadData($input);
250
+
251
+        // Run create hooks
252
+        foreach ($transaction->registeredCreateHooks as $colName => $fn) {
253
+            $fn();
254
+        }
255
+
256
+        // Validate missing keys
257
+        $errors += $transaction->validateMissingKeys($input);
258
+
259
+        // If no errors, commit the pending data
260
+        if (empty($errors)) {
261
+            $this->syncInstanceFrom($transaction);
262
+
263
+            // Insert default values for not-null fields
264
+            foreach ($this->tableDefinition as $colName => $colDef) {
265
+                if ($this->tableDefinition[$colName]['value'] === null
266
+                    && isset($this->tableDefinition[$colName]['properties'])
267
+                    && $this->tableDefinition[$colName]['properties'] && ColumnProperty::NOT_NULL > 0
268
+                    && isset($this->tableDefinition[$colName]['default'])) {
269
+                    $this->tableDefinition[$colName]['value'] = $this->tableDefinition[$colName]['default'];
270
+                }
271
+            }
272
+
273
+            try {
274
+                (new Query($this->getPdo(), $this->getTableName()))
275
+                    ->insert($this->getActiveRecordColumns())
276
+                    ->execute();
277
+
278
+                $this->setId(intval($this->getPdo()->lastInsertId()));
279
+            } catch (\PDOException $e) {
280
+                // @TODO: Potentially filter and store mysql messages (where possible) in error messages
281
+                throw new ActiveRecordException($e->getMessage(), 0, $e);
282
+            }
283
+
284
+            return [null, $this->toArray($readWhitelist)];
285
+        } else {
286
+            return [$errors, null];
287
+        }
288
+    }
289
+
290
+    /**
291
+     * @param Array $input Associative array of input values
292
+     * @param Array $fieldWhitelist array of column names that are allowed to be filled by the input array 
293
+     * @return Array Array containing the set of optional errors (associative array) and an optional array representation (associative)
294
+     * 					of the modified data.
295
+     */
296
+    public function apiUpdate($input, Array $updateWhitelist, Array $readWhitelist)
297
+    {
298
+        $transaction = $this->newInstance();
299
+        $transaction->syncInstanceFrom($this);
300
+        $errors = [];
301
+
302
+        // Filter out all non-whitelisted input values
303
+        $input = $this->filterInputColumns($input, $updateWhitelist);
304
+
305
+        // Check for excess keys
306
+        $errors += $transaction->validateExcessKeys($input);
307
+
308
+        // Check for immutable keys
309
+        $errors += $transaction->validateImmutableColumns($input);
310
+
311
+        // Validate input values (using validation function)
312
+        $errors += $transaction->validateInputValues($input);
313
+
314
+        // "Copy" data into transaction
315
+        $transaction->loadData($input);
316
+
317
+        // Run create hooks
318
+        foreach ($transaction->registeredUpdateHooks as $colName => $fn) {
319
+            $fn();
320
+        }
321
+
322
+        // Validate missing keys
323
+        $errors += $transaction->validateMissingKeys($input);
324
+
325
+        // Update database
326
+        if (empty($errors)) {
327
+            $this->syncInstanceFrom($transaction);
328
+
329
+            try {
330
+                (new Query($this->getPdo(), $this->getTableName()))
331
+                    ->update($this->getActiveRecordColumns())
332
+                    ->where(Query::Equal('id', $this->getId()))
333
+                    ->execute();
334
+            } catch (\PDOException $e) {
335
+                throw new ActiveRecordException($e->getMessage(), 0, $e);
336
+            }
337
+
338
+            return [null, $this->toArray($readWhitelist)];
339
+        } else {
340
+            return [$errors, null];
341
+        }
342
+    }
343
+
344
+    /**
345
+     * Returns this active record after reading the attributes from the entry with the given identifier.
346
+     *
347
+     * @param mixed $id
348
+     * @return $this
349
+     * @throws ActiveRecordException on failure.
350
+     */
351
+    abstract public function read($id);
352
+
353
+    /**
354
+     * Returns the PDO.
355
+     *
356
+     * @return \PDO the PDO.
357
+     */
358
+    abstract public function getPdo();
359
+
360
+    /**
361
+     * Set the ID.
362
+     *
363
+     * @param int $id
364
+     * @return $this
365
+     */
366
+    abstract protected function setId($id);
367
+
368
+    /**
369
+     * Returns the ID.
370
+     *
371
+     * @return null|int The ID.
372
+     */
373
+    abstract protected function getId();
374
+
375
+    /**
376
+     * Returns the active record table.
377
+     *
378
+     * @return string the active record table name.
379
+     */
380
+    abstract protected function getTableName();
381
+
382
+    /**
383
+     * Returns the name -> variable mapping for the table definition.
384
+     * @return Array The mapping
385
+     */
386
+    abstract protected function getActiveRecordColumns();
387 387
 }
Please login to merge, or discard this patch.