Skip to content

Commit daaf78a

Browse files
committed
PHPDoc, a new test, and cryptographically save session handle maker
Methods that return Models from ActiveRecord and VersionedRecord will now return static[] and static which is more accurate PHPDoc notation. Session method generateUniqueHandle is now cryptographically secure with 2^128 possible handles. Added binary type support to SQL class. Added a test for Session generateUniqueHandle
1 parent a5594ee commit daaf78a

6 files changed

Lines changed: 125 additions & 51 deletions

File tree

src/IO/Database/SQL.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ public static function getSQLType($field)
197197
return 'text';
198198
case 'blob':
199199
return 'blob';
200+
case 'binary':
201+
return 'binary';
200202

201203
case 'timestamp':
202204
return 'timestamp';

src/Models/ActiveRecord.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ class ActiveRecord implements JsonSerializable
283283
*
284284
* @uses static::init
285285
*
286-
* @return ActiveRecord Instance of the value of $this->Class
286+
* @return static Instance of the value of $this->Class
287287
*/
288288
public function __construct($record = [], $isDirty = false, $isPhantom = null)
289289
{
@@ -508,7 +508,7 @@ public static function isRelational()
508508
*
509509
* @param array $values Array of keys as fields and values.
510510
* @param boolean $save If the object should be immediately saved to database before being returned.
511-
* @return ActiveRecord An object of this model.
511+
* @return static An object of this model.
512512
*/
513513
public static function create($values = [], $save = false)
514514
{
@@ -540,7 +540,7 @@ public function isA($class)
540540
*
541541
* @param string $className If you leave this blank the return will be $this
542542
* @param array $fieldValues Optional. Any field values you want to override.
543-
* @return ActiveRecord A new model of a different class with this model's field's. Useful when you have similar classes or subclasses with the same parent.
543+
* @return static A new model of a different class with this model's field's. Useful when you have similar classes or subclasses with the same parent.
544544
*/
545545
public function changeClass($className = false, $fieldValues = false)
546546
{
@@ -842,7 +842,7 @@ public static function getByHandle($handle)
842842
* Get model object by primary key.
843843
*
844844
* @param int $id
845-
* @return ActiveRecord|null
845+
* @return static|null
846846
*/
847847
public static function getByID($id)
848848
{
@@ -857,7 +857,7 @@ public static function getByID($id)
857857
* @param string $field Field name
858858
* @param string $value Field value
859859
* @param boolean $cacheIndex Optional. If we should cache the result or not. Default is false.
860-
* @return ActiveRecord|null
860+
* @return static|null
861861
*/
862862
public static function getByField($field, $value, $cacheIndex = false)
863863
{
@@ -896,7 +896,7 @@ public static function getRecordByField($field, $value, $cacheIndex = false)
896896
*
897897
* @param array|string $conditions If passed as a string a database Where clause. If an array of field/value pairs will convert to a series of `field`='value' conditions joined with an AND operator.
898898
* @param array|string $options Only takes 'order' option. A raw database string that will be inserted into the OR clause of the query or an array of field/direction pairs.
899-
* @return ActiveRecord|null Single model instantiated from the first database result
899+
* @return static|null Single model instantiated from the first database result
900900
*/
901901
public static function getByWhere($conditions, $options = [])
902902
{
@@ -944,7 +944,7 @@ public static function getRecordByWhere($conditions, $options = [])
944944
*
945945
* @param string $query Database query. The passed in string will be passed through vsprintf or sprintf with $params.
946946
* @param array|string $params If an array will be passed through vsprintf as the second parameter with the query as the first. If a string will be used with sprintf instead. If nothing provided you must provide your own query.
947-
* @return ActiveRecord|null Single model instantiated from the first database result
947+
* @return static|null Single model instantiated from the first database result
948948
*/
949949
public static function getByQuery($query, $params = [])
950950
{
@@ -956,7 +956,7 @@ public static function getByQuery($query, $params = [])
956956
*
957957
* @param boolean $className The full name of the class including namespace. Optional. Will use the name of the current class if none provided.
958958
* @param array $options
959-
* @return ActiveRecord[]|null Array of instantiated ActiveRecord models returned from the database result.
959+
* @return static[]|null Array of instantiated ActiveRecord models returned from the database result.
960960
*/
961961
public static function getAllByClass($className = false, $options = [])
962962
{
@@ -968,7 +968,7 @@ public static function getAllByClass($className = false, $options = [])
968968
*
969969
* @param ActiveRecord $Record
970970
* @param array $options
971-
* @return ActiveRecord[]|null Array of instantiated ActiveRecord models returned from the database result.
971+
* @return static[]|null Array of instantiated ActiveRecord models returned from the database result.
972972
*/
973973
public static function getAllByContextObject(ActiveRecord $Record, $options = [])
974974
{
@@ -998,7 +998,7 @@ public static function getAllByContext($contextClass, $contextID, $options = [])
998998
* @param string $field Field name
999999
* @param string $value Field value
10001000
* @param array $options
1001-
* @return ActiveRecord[]|null Array of models instantiated from the database result.
1001+
* @return static[]|null Array of models instantiated from the database result.
10021002
*/
10031003
public static function getAllByField($field, $value, $options = [])
10041004
{
@@ -1010,7 +1010,7 @@ public static function getAllByField($field, $value, $options = [])
10101010
*
10111011
* @param array|string $conditions If passed as a string a database Where clause. If an array of field/value pairs will convert to a series of `field`='value' conditions joined with an AND operator.
10121012
* @param array|string $options
1013-
* @return ActiveRecord[]|null Array of models instantiated from the database result.
1013+
* @return static[]|null Array of models instantiated from the database result.
10141014
*/
10151015
public static function getAllByWhere($conditions = [], $options = [])
10161016
{
@@ -1113,7 +1113,7 @@ public static function getAllRecordsByWhere($conditions = [], $options = [])
11131113
* Attempts to get all database records for this class and return them as an array of instantiated models.
11141114
*
11151115
* @param array $options
1116-
* @return ActiveRecord[]|null
1116+
* @return static[]|null
11171117
*/
11181118
public static function getAll($options = [])
11191119
{
@@ -1161,7 +1161,7 @@ public static function getAllRecords($options = [])
11611161
*
11621162
* @param string $query Database query. The passed in string will be passed through vsprintf or sprintf with $params.
11631163
* @param array|string $params If an array will be passed through vsprintf as the second parameter with the query as the first. If a string will be used with sprintf instead. If nothing provided you must provide your own query.
1164-
* @return ActiveRecord[]|null Array of models instantiated from the first database result
1164+
* @return static[]|null Array of models instantiated from the first database result
11651165
*/
11661166
public static function getAllByQuery($query, $params = [])
11671167
{
@@ -1178,7 +1178,7 @@ public static function getTableByQuery($keyField, $query, $params = [])
11781178
* Converts database record array to a model. Will attempt to use the record's Class field value to as the class to instantiate as or the name of this class if none is provided.
11791179
*
11801180
* @param array $record Database row as an array.
1181-
* @return ActiveRecord|null An instantiated ActiveRecord model from the provided data.
1181+
* @return static|null An instantiated ActiveRecord model from the provided data.
11821182
*/
11831183
public static function instantiateRecord($record)
11841184
{
@@ -1190,7 +1190,7 @@ public static function instantiateRecord($record)
11901190
* Converts an array of database records to a model corresponding to each record. Will attempt to use the record's Class field value to as the class to instantiate as or the name of this class if none is provided.
11911191
*
11921192
* @param array $record An array of database rows.
1193-
* @return ActiveRecord|null An array of instantiated ActiveRecord models from the provided data.
1193+
* @return static|null An array of instantiated ActiveRecord models from the provided data.
11941194
*/
11951195
public static function instantiateRecords($records)
11961196
{

src/Models/Auth/Session.php

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
* Session object
1818
*
1919
* @author Henry Paradiz <henry.paradiz@gmail.com>
20-
* @author Chris Alfano <themightychris@gmail.com>
21-
*
22-
* {@inheritDoc}
20+
* @author Chris Alfano <themightychris@gmail.com>
21+
* @inheritDoc
22+
* @property string $Handle Unique identifier for this session used by the cookie.
23+
* @property string $LastRequest Timestamp of the last time this session was updated.
24+
* @property string $Binary Actually raw binary in the string
2325
*/
2426
class Session extends Model
2527
{
@@ -59,18 +61,13 @@ class Session extends Model
5961
];
6062

6163

62-
// Session
63-
public static function __classLoaded()
64-
{
65-
parent::__classLoaded();
66-
67-
// auto-detect cookie domain
68-
if (empty(static::$cookieDomain)) {
69-
static::$cookieDomain = preg_replace('/^www\.([^.]+\.[^.]+)$/i', '$1', $_SERVER['HTTP_HOST']);
70-
}
71-
}
72-
73-
64+
/**
65+
* Gets or sets up a session based on current cookies.
66+
* Will always update the current session's LastIP and LastRequest fields.
67+
*
68+
* @param boolean $create
69+
* @return static|false
70+
*/
7471
public static function getFromRequest($create = true)
7572
{
7673
$sessionData = [
@@ -129,6 +126,12 @@ public static function updateSession(Session $Session, $sessionData)
129126
}
130127
}
131128

129+
/**
130+
* Gets by handle.
131+
*
132+
* @param string $handle
133+
* @return static
134+
*/
132135
public static function getByHandle($handle)
133136
{
134137
return static::getByField('Handle', $handle, true);
@@ -142,6 +145,15 @@ public function getData()
142145
]);
143146
}
144147

148+
/**
149+
* @inheritDoc
150+
*
151+
* Saves the session to the database and sets the session cookie.
152+
* Will generate a unique handle for the session if none exists.
153+
*
154+
* @param boolean $deep
155+
* @return void
156+
*/
145157
public function save($deep = true)
146158
{
147159
// set handle
@@ -163,6 +175,13 @@ public function save($deep = true)
163175
);
164176
}
165177

178+
/**
179+
* Attempts to unset the cookie.
180+
* Unsets the variable from the $_COOKIE global.
181+
* Deletes session from database.
182+
*
183+
* @return void
184+
*/
166185
public function terminate()
167186
{
168187
setcookie(static::$cookieName, '', time() - 3600);
@@ -173,11 +192,20 @@ public function terminate()
173192

174193

175194

195+
/**
196+
* Makes a random 32 digit string by generating 16 random bytes
197+
* Is cryptographically secure.
198+
* @see http://php.net/manual/en/function.random-bytes.php
199+
*
200+
* @return void
201+
*/
176202
public static function generateUniqueHandle()
177203
{
178204
do {
179-
$handle = md5(mt_rand(0, mt_getrandmax()));
205+
$handle = bin2hex(random_bytes(16));
180206
} while (static::getByHandle($handle));
207+
// just in case checks if the handle exists in the database and if it does makes a new one.
208+
// chance of happening is 1 in 2^128 though so might want to remove the database call
181209

182210
return $handle;
183211
}

src/Models/Media/Media.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ class Media extends Model
3434
public static $subClasses = [__CLASS__, Image::class, PDF::class, Video::class, Audio::class];
3535
public static $collectionRoute = '/media';
3636

37-
// get rid of these??
38-
public static $Namespaces = [];
39-
public static $Types = [];
40-
41-
4237
public static $tableName = 'media';
4338

4439
public static $fields = [

src/Models/Versioning.php

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
*
2020
* @package Divergence
2121
* @author Henry Paradiz <henry.paradiz@gmail.com>
22-
*
22+
* @inheritDoc
23+
* @property int $RevisionID ID of revision in the history table.
24+
* @property static[] $History All revisions for this object. This is hooked in the Relations trait.
2325
*/
2426
trait Versioning
2527
{
@@ -33,39 +35,62 @@ trait Versioning
3335
'notnull' => false,
3436
],
3537
];
36-
38+
3739
public static $versioningRelationships = [
3840
'History' => [
3941
'type' => 'history',
4042
'order' => ['RevisionID' => 'DESC'],
4143
],
4244
];
43-
44-
45+
46+
/**
47+
* Returns static::$historyTable
48+
*
49+
* @throws Exception If static::$historyTable is not set.
50+
* @return string
51+
*/
4552
public static function getHistoryTable()
4653
{
4754
if (!static::$historyTable) {
4855
throw new Exception('Static variable $historyTable must be defined to use model versioning.');
4956
}
50-
57+
5158
return static::$historyTable;
5259
}
53-
54-
/*
55-
* Implement specialized getters
60+
61+
/**
62+
* The history table allows multiple records with the same ID.
63+
* The primary key becomes RevisionID.
64+
* This returns all the revisions by ID so you will get the history of that object.
65+
*
66+
* @return static[] Revisions by ID
5667
*/
5768
public static function getRevisionsByID($ID, $options = [])
5869
{
5970
$options['conditions'][static::getPrimaryKey()] = $ID;
60-
71+
6172
return static::getRevisions($options);
6273
}
6374

75+
/**
76+
* Gets all versions of all objects for this object.
77+
*
78+
* Use getRevisionsByID instead.
79+
*
80+
* @param array $options Query options
81+
* @return static[] Revisions
82+
*/
6483
public static function getRevisions($options = [])
6584
{
6685
return static::instantiateRecords(static::getRevisionRecords($options));
6786
}
68-
87+
88+
/**
89+
* Gets raw revision data from the database and constructs a query
90+
*
91+
* @param array $options Query options
92+
* @return array
93+
*/
6994
public static function getRevisionRecords($options = [])
7095
{
7196
$options = Util::prepareOptions($options, [
@@ -75,29 +100,34 @@ public static function getRevisionRecords($options = [])
75100
'limit' => false,
76101
'offset' => 0,
77102
]);
78-
103+
79104
$query = 'SELECT * FROM `%s` WHERE (%s)';
80105
$params = [
81106
static::getHistoryTable(),
82107
count($options['conditions']) ? join(') AND (', static::_mapConditions($options['conditions'])) : 1,
83108
];
84-
109+
85110
if ($options['order']) {
86111
$query .= ' ORDER BY ' . join(',', static::_mapFieldOrder($options['order']));
87112
}
88-
113+
89114
if ($options['limit']) {
90115
$query .= sprintf(' LIMIT %u,%u', $options['offset'], $options['limit']);
91116
}
92-
93-
117+
118+
94119
if ($options['indexField']) {
95120
return DB::table(static::_cn($options['indexField']), $query, $params);
96121
} else {
97122
return DB::allRecords($query, $params);
98123
}
99124
}
100125

126+
/**
127+
* Sets wasDirty, isDirty, Created for the object before save
128+
*
129+
* @return void
130+
*/
101131
public function beforeVersionedSave()
102132
{
103133
$this->wasDirty = false;
@@ -108,6 +138,11 @@ public function beforeVersionedSave()
108138
}
109139
}
110140

141+
/**
142+
* After save to regular database this saves to the history table
143+
*
144+
* @return void
145+
*/
111146
public function afterVersionedSave()
112147
{
113148
if ($this->wasDirty && static::$createRevisionOnSave) {

0 commit comments

Comments
 (0)