Completed
Branch 09branch (946dde)
by Anton
05:16
created

SqlTimestamp   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 74
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 74
rs 10
c 0
b 0
f 0
wmc 8
lcom 2
cbo 4

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A fetchTimestamp() 0 4 1
A compileUpdates() 0 4 1
B fetchSourceTimezone() 0 23 5
1
<?php
2
/**
3
 * spiral
4
 *
5
 * @author    Wolfy-J
6
 */
7
8
namespace Spiral\Models\Accessors;
9
10
use Spiral\Models\Exceptions\AccessorException;
11
use Spiral\ORM\ORMInterface;
12
use Spiral\ORM\RecordAccessorInterface;
13
14
/**
15
 * Field to timestamp accessor for ORM Records. Automatically fetches database timezone and caches
16
 * it.
17
 */
18
class SqlTimestamp extends AbstractTimestamp implements RecordAccessorInterface
19
{
20
    /**
21
     * Cached list of record timezones.
22
     *
23
     * @var array
24
     */
25
    private static $recordTimezones = [];
26
27
    /**
28
     * @var \DateTimeZone
29
     */
30
    private $sourceTimezone;
31
32
    /**
33
     * @param string $value
34
     * @param array  $context
35
     */
36
    public function __construct($value, array $context)
37
    {
38
        $this->sourceTimezone = $this->fetchSourceTimezone($context);
39
        parent::__construct($value, $context);
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    protected function fetchTimestamp($value): int
46
    {
47
        return $this->castTimestamp($value, $this->sourceTimezone) ?? 0;
48
    }
49
50
    /**
51
     * @param string $field
52
     *
53
     * @return \DateTimeInterface
54
     */
55
    public function compileUpdates(string $field = '')
56
    {
57
        return $this->packValue();
58
    }
59
60
    /**
61
     * Must locate source timezone, but default checks cache and then performs fallback to
62
     * Driver based check.
63
     *
64
     * @param array $context
65
     *
66
     * @return \DateTimeZone
67
     */
68
    private function fetchSourceTimezone(array $context): \DateTimeZone
69
    {
70
        if (empty($context['entity']) || empty($context['orm'])) {
71
            throw new AccessorException("Invalid accessor context, expected [entity, orm]");
72
        }
73
74
        $class = get_class($context['entity']);
75
76
        if (!empty(self::$recordTimezones[$class])) {
77
            //Found in static cache
78
            return self::$recordTimezones[$class];
79
        }
80
81
        $orm = $context['orm'];
82
        if (!$orm instanceof ORMInterface) {
83
            throw new AccessorException("Invalid accessor context, ORMInterface expected");
84
        }
85
86
        //Timezone thought driver
87
        return $orm->database(
88
            $orm->define($class, ORMInterface::R_DATABASE)
89
        )->getDriver()->getTimezone();
90
    }
91
}