Skip to content

Commit 07d039e

Browse files
authored
Merge pull request #21 from Divergence/develop
v2.1.1
2 parents e4b72f4 + 27c619b commit 07d039e

13 files changed

Lines changed: 270 additions & 166 deletions

File tree

src/Controllers/MediaRequestHandler.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,11 @@ public function respondWithMedia(Media $Media, $variant, $responseID, $responseD
328328

329329
// if partial content provide proper response header
330330
if (isset($chunkStart)) {
331-
$response = $response->withStatus(206)
332-
->withHeader('Content-Range', "bytes $start-$end/$size")
331+
// only send 206 if response is less than the whole file
332+
if ($end-$start+1<$size) {
333+
$response = $response->withStatus(206);
334+
}
335+
$response = $response->withHeader('Content-Range', "bytes $start-$end/$size")
333336
->withHeader('Content-Length', $length);
334337
} else {
335338
// range

src/Models/ActiveRecord.php

Lines changed: 71 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
use Divergence\IO\Database\Query\Delete;
2222
use Divergence\IO\Database\Query\Insert;
2323
use Divergence\IO\Database\Query\Update;
24-
use Divergence\Models\Interfaces\FieldSetMapper;
25-
use Divergence\Models\SetMappers\DefaultSetMapper;
24+
use Divergence\Models\Mapping\DefaultGetMapper;
25+
use Divergence\Models\Mapping\DefaultSetMapper;
2626

2727
/**
2828
* ActiveRecord
@@ -290,9 +290,9 @@ class ActiveRecord implements JsonSerializable
290290
*/
291291
protected $_isUpdated;
292292

293-
/** Field Mapper */
294-
protected ?FieldSetMapper $fieldSetMapper;
295293

294+
public const defaultSetMapper = DefaultSetMapper::class;
295+
public const defaultGetMapper = DefaultGetMapper::class;
296296
/**
297297
* __construct Instantiates a Model and returns.
298298
*
@@ -404,6 +404,11 @@ public function getPrimaryKeyValue()
404404
public static function init()
405405
{
406406
$className = get_called_class();
407+
408+
$className::$rootClass = $className::$rootClass ?? $className;
409+
$className::$defaultClass = $className::$defaultClass ?? $className;
410+
$className::$subClasses = $className::$subClasses ?? [$className];
411+
407412
if (empty(static::$_fieldsDefined[$className])) {
408413
static::_defineFields();
409414
static::_initFields();
@@ -1118,7 +1123,7 @@ public static function _definedAttributeFields(): array
11181123
// skip these because they are built in
11191124
if (in_array($property->getName(), [
11201125
'_classFields','_classRelationships','_classBeforeSave','_classAfterSave','_fieldsDefined','_relationshipsDefined','_eventsDefined','_record','_validator'
1121-
,'_validationErrors','_isDirty','_isValid','fieldSetMapper','_convertedValues','_originalValues','_isPhantom','_wasPhantom','_isNew','_isUpdated','_relatedObjects'
1126+
,'_validationErrors','_isDirty','_isValid','_convertedValues','_originalValues','_isPhantom','_wasPhantom','_isNew','_isUpdated','_relatedObjects'
11221127
])) {
11231128
continue;
11241129
}
@@ -1245,8 +1250,21 @@ protected static function _cn($field)
12451250
}
12461251

12471252

1253+
private function applyNewValue($type, $field, $value)
1254+
{
1255+
if (!isset($this->_convertedValues[$field])) {
1256+
if (is_null($value) && !in_array($type, ['set','list'])) {
1257+
unset($this->_convertedValues[$field]);
1258+
return null;
1259+
}
1260+
$this->_convertedValues[$field] = $value;
1261+
}
1262+
return $this->_convertedValues[$field];
1263+
}
1264+
12481265
/**
1249-
* Retrieves given field's value
1266+
* Applies type-dependent transformations to the value in $this->_record[$fieldOptions['columnName']]
1267+
* Caches to $this->_convertedValues[$field] and returns the value in there.
12501268
* @param string $field Name of field
12511269
* @return mixed value
12521270
*/
@@ -1257,81 +1275,34 @@ protected function _getFieldValue($field, $useDefault = true)
12571275
if (isset($this->_record[$fieldOptions['columnName']])) {
12581276
$value = $this->_record[$fieldOptions['columnName']];
12591277

1278+
$defaultGetMapper = static::defaultGetMapper;
1279+
12601280
// apply type-dependent transformations
12611281
switch ($fieldOptions['type']) {
1262-
case 'password':
1263-
{
1264-
return $value;
1265-
}
1266-
12671282
case 'timestamp':
1268-
{
1269-
if (!isset($this->_convertedValues[$field])) {
1270-
if ($value && is_string($value) && $value != '0000-00-00 00:00:00') {
1271-
$this->_convertedValues[$field] = strtotime($value);
1272-
} elseif (is_integer($value)) {
1273-
$this->_convertedValues[$field] = $value;
1274-
} else {
1275-
unset($this->_convertedValues[$field]);
1276-
}
1277-
}
1283+
return $this->applyNewValue($fieldOptions['type'], $field, $defaultGetMapper::getTimestampValue($value));
12781284

1279-
return $this->_convertedValues[$field];
1280-
}
12811285
case 'serialized':
1282-
{
1283-
if (!isset($this->_convertedValues[$field])) {
1284-
$this->_convertedValues[$field] = is_string($value) ? unserialize($value) : $value;
1285-
}
1286+
return $this->applyNewValue($fieldOptions['type'], $field, $defaultGetMapper::getSerializedValue($value));
12861287

1287-
return $this->_convertedValues[$field];
1288-
}
12891288
case 'set':
12901289
case 'list':
1291-
{
1292-
if (!isset($this->_convertedValues[$field])) {
1293-
$delim = empty($fieldOptions['delimiter']) ? ',' : $fieldOptions['delimiter'];
1294-
$this->_convertedValues[$field] = array_filter(preg_split('/\s*'.$delim.'\s*/', $value));
1295-
}
1296-
1297-
return $this->_convertedValues[$field];
1298-
}
1290+
return $this->applyNewValue($fieldOptions['type'], $field, $defaultGetMapper::getListValue($value, $fieldOptions['delimiter']));
12991291

13001292
case 'int':
13011293
case 'integer':
13021294
case 'uint':
1303-
if (!isset($this->_convertedValues[$field])) {
1304-
if (!$fieldOptions['notnull'] && is_null($value)) {
1305-
$this->_convertedValues[$field] = $value;
1306-
} else {
1307-
$this->_convertedValues[$field] = intval($value);
1308-
}
1309-
}
1310-
return $this->_convertedValues[$field];
1295+
return $this->applyNewValue($fieldOptions['type'], $field, $defaultGetMapper::getIntegerValue($value));
13111296

13121297
case 'boolean':
1313-
{
1314-
if (!isset($this->_convertedValues[$field])) {
1315-
$this->_convertedValues[$field] = (bool)$value;
1316-
}
1317-
1318-
return $this->_convertedValues[$field];
1319-
}
1298+
return $this->applyNewValue($fieldOptions['type'], $field, $defaultGetMapper::getBooleanValue($value));
13201299

13211300
case 'decimal':
1322-
if (!isset($this->_convertedValues[$field])) {
1323-
if (!$fieldOptions['notnull'] && is_null($value)) {
1324-
$this->_convertedValues[$field] = $value;
1325-
} else {
1326-
$this->_convertedValues[$field] = floatval($value);
1327-
}
1328-
}
1329-
return $this->_convertedValues[$field];
1301+
return $this->applyNewValue($fieldOptions['type'], $field, $defaultGetMapper::getDecimalValue($value));
13301302

1303+
case 'password':
13311304
default:
1332-
{
1333-
return $value;
1334-
}
1305+
return $value;
13351306
}
13361307
} elseif ($useDefault && isset($fieldOptions['default'])) {
13371308
// return default
@@ -1340,13 +1311,9 @@ protected function _getFieldValue($field, $useDefault = true)
13401311
switch ($fieldOptions['type']) {
13411312
case 'set':
13421313
case 'list':
1343-
{
1344-
return [];
1345-
}
1314+
return [];
13461315
default:
1347-
{
1348-
return null;
1349-
}
1316+
return null;
13501317
}
13511318
}
13521319
}
@@ -1376,17 +1343,15 @@ protected function _setFieldValue($field, $value)
13761343
return false;
13771344
}
13781345

1379-
if (!isset($this->fieldSetMapper)) {
1380-
$this->fieldSetMapper = new DefaultSetMapper();
1381-
}
1346+
$setMapper = static::defaultSetMapper;
13821347

13831348
// pre-process value
13841349
$forceDirty = false;
13851350
switch ($fieldOptions['type']) {
13861351
case 'clob':
13871352
case 'string':
13881353
{
1389-
$value = $this->fieldSetMapper->setStringValue($value);
1354+
$value = $setMapper::setStringValue($value);
13901355
if (!$fieldOptions['notnull'] && $fieldOptions['blankisnull'] && ($value === '' || $value === null)) {
13911356
$value = null;
13921357
}
@@ -1395,21 +1360,21 @@ protected function _setFieldValue($field, $value)
13951360

13961361
case 'boolean':
13971362
{
1398-
$value = $this->fieldSetMapper->setBooleanValue($value);
1363+
$value = $setMapper::setBooleanValue($value);
13991364
break;
14001365
}
14011366

14021367
case 'decimal':
14031368
{
1404-
$value = $this->fieldSetMapper->setDecimalValue($value);
1369+
$value = $setMapper::setDecimalValue($value);
14051370
break;
14061371
}
14071372

14081373
case 'int':
14091374
case 'uint':
14101375
case 'integer':
14111376
{
1412-
$value = $this->fieldSetMapper->setIntegerValue($value);
1377+
$value = $setMapper::setIntegerValue($value);
14131378
if (!$fieldOptions['notnull'] && ($value === '' || is_null($value))) {
14141379
$value = null;
14151380
}
@@ -1419,67 +1384,71 @@ protected function _setFieldValue($field, $value)
14191384
case 'timestamp':
14201385
{
14211386
unset($this->_convertedValues[$field]);
1422-
$value = $this->fieldSetMapper->setTimestampValue($value);
1387+
$value = $setMapper::setTimestampValue($value);
14231388
break;
14241389
}
14251390

14261391
case 'date':
14271392
{
14281393
unset($this->_convertedValues[$field]);
1429-
$value = $this->fieldSetMapper->setDateValue($value);
1394+
$value = $setMapper::setDateValue($value);
14301395
break;
14311396
}
14321397

1433-
// these types are converted to strings from another PHP type on save
14341398
case 'serialized':
14351399
{
1436-
// if the value is a string we assume it's already serialized data
14371400
if (!is_string($value)) {
1438-
$value = $this->fieldSetMapper->setSerializedValue($value);
1401+
$value = $setMapper::setSerializedValue($value);
14391402
}
14401403
break;
14411404
}
14421405
case 'enum':
14431406
{
1444-
$value = $this->fieldSetMapper->setEnumValue($fieldOptions['values'], $value);
1407+
$value = $setMapper::setEnumValue($fieldOptions['values'], $value);
14451408
break;
14461409
}
14471410
case 'set':
14481411
case 'list':
14491412
{
1450-
$value = $this->fieldSetMapper->setListValue($value, isset($fieldOptions['delimiter']) ? $fieldOptions['delimiter'] : null);
1413+
$value = $setMapper::setListValue($value, isset($fieldOptions['delimiter']) ? $fieldOptions['delimiter'] : null);
14511414
$this->_convertedValues[$field] = $value;
14521415
$forceDirty = true;
14531416
break;
14541417
}
14551418
}
14561419

14571420
if ($forceDirty || (empty($this->_record[$field]) && isset($value)) || ($this->_record[$field] !== $value)) {
1458-
$columnName = static::_cn($field);
1459-
if (isset($this->_record[$columnName])) {
1460-
$this->_originalValues[$field] = $this->_record[$columnName];
1461-
}
1462-
$this->_record[$columnName] = $value;
1463-
// only set value if this is an attribute mapped field
1464-
if (isset($this->_classFields[get_called_class()][$columnName]['attributeField'])) {
1465-
$this->$columnName = $value;
1466-
}
1467-
$this->_isDirty = true;
1468-
1469-
// unset invalidated relationships
1470-
if (!empty($fieldOptions['relationships']) && static::isRelational()) {
1471-
foreach ($fieldOptions['relationships'] as $relationship => $isCached) {
1472-
if ($isCached) {
1473-
unset($this->_relatedObjects[$relationship]);
1474-
}
1475-
}
1476-
}
1421+
$this->_setValueAndMarkDirty($field, $value, $fieldOptions);
14771422
return true;
14781423
} else {
14791424
return false;
14801425
}
14811426
}
14821427

1428+
protected function _setValueAndMarkDirty($field, $value, $fieldOptions)
1429+
{
1430+
$columnName = static::_cn($field);
1431+
if (isset($this->_record[$columnName])) {
1432+
$this->_originalValues[$field] = $this->_record[$columnName];
1433+
}
1434+
$this->_record[$columnName] = $value;
1435+
// only set value if this is an attribute mapped field
1436+
if (isset(static::$_classFields[get_called_class()][$columnName]['attributeField'])) {
1437+
$this->$columnName = $value;
1438+
}
1439+
$this->_isDirty = true;
1440+
1441+
// If a model has been modified we should clear the relationship cache
1442+
// TODO: this can be smarter by only looking at fields that are used in the relationship configuration
1443+
if (!empty($fieldOptions['relationships']) && static::isRelational()) {
1444+
foreach ($fieldOptions['relationships'] as $relationship => $isCached) {
1445+
if ($isCached) {
1446+
unset($this->_relatedObjects[$relationship]);
1447+
}
1448+
}
1449+
}
1450+
}
1451+
14831452
protected function _prepareRecordValues()
14841453
{
14851454
$record = [];
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
/**
3+
* This file is part of the Divergence package.
4+
*
5+
* (c) Henry Paradiz <henry.paradiz@gmail.com>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Divergence\Models\Interfaces;
12+
13+
/**
14+
* Field Get Mapper interface
15+
*
16+
* This is how each Model field type is processed.
17+
*
18+
* @package Divergence
19+
* @author Henry Paradiz <henry.paradiz@gmail.com>
20+
*
21+
*/
22+
interface FieldGetMapper
23+
{
24+
public static function getStringValue($value): ?string;
25+
public static function getBooleanValue($value): bool;
26+
public static function getDecimalValue($value): ?float;
27+
public static function getIntegerValue($value): ?int;
28+
public static function getDateValue($value);
29+
public static function getTimestampValue($value): ?int;
30+
public static function getSerializedValue($value);
31+
public static function getListValue($value, ?string $delimiter): array;
32+
}

src/Models/Interfaces/FieldSetMapper.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
*/
2222
interface FieldSetMapper
2323
{
24-
public function setStringValue($value): ?string;
25-
public function setBooleanValue($value): bool;
26-
public function setDecimalValue($value): ?float;
27-
public function setIntegerValue($value): ?int;
28-
public function setDateValue($value): ?string;
29-
public function setTimestampValue($value): ?string;
30-
public function setSerializedValue($value): string;
31-
public function setEnumValue(array $values, $value);
32-
public function setListValue($value, ?string $delimiter): array;
24+
public static function setStringValue($value): ?string;
25+
public static function setBooleanValue($value): bool;
26+
public static function setDecimalValue($value): ?float;
27+
public static function setIntegerValue($value): ?int;
28+
public static function setDateValue($value): ?string;
29+
public static function setTimestampValue($value): ?string;
30+
public static function setSerializedValue($value): string;
31+
public static function setEnumValue(array $values, $value);
32+
public static function setListValue($value, ?string $delimiter): array;
3333
}

0 commit comments

Comments
 (0)