Passed
Push — sheepy/introspection ( 9a33c8...7d1300 )
by Marco
05:54
created

DataResolver::resolveDataObject()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
c 0
b 0
f 0
dl 0
loc 21
rs 9.2222
cc 6
nc 5
nop 0
1
<?php
2
3
namespace Firesphere\SolrSearch\Helpers;
4
5
use Exception;
6
use SilverStripe\ORM\DataObject;
7
use SilverStripe\ORM\FieldType\DBField;
8
use SilverStripe\ORM\SS_List;
9
use SilverStripe\View\ArrayData;
10
11
class DataResolver
12
{
13
    protected $component;
14
    protected $columns = [];
15
    protected $columnName = '';
16
17
    public function __construct($component, $columns = [])
18
    {
19
        if (!is_array($columns)) {
20
            $columns = array_filter(explode('.', $columns));
21
        }
22
        $this->columns = $columns;
23
        $this->component = $component;
24
        $this->columnName = $this->columns ? array_shift($this->columns) : null;
25
    }
26
27
    /**
28
     * @param DataObject|ArrayData|SS_List $obj
29
     * @param array|string $columns
30
     *
31
     * @return mixed
32
     * @throws Exception
33
     */
34
    public static function identify($obj, $columns = [])
35
    {
36
        $instance = new self($obj, $columns);
37
        if ($obj instanceof DataObject) {
38
            return $instance->resolveDataObject();
39
        }
40
        if ($obj instanceof ArrayData) {
41
            return $instance->resolveArrayData();
42
        }
43
        if ($obj instanceof SS_List) {
0 ignored issues
show
introduced by
$obj is always a sub-type of SilverStripe\ORM\SS_List.
Loading history...
44
            return $instance->resolveList();
45
        }
46
        if ($obj instanceof DBField) {
47
            return $instance->resolveField();
48
        }
49
        throw new Exception(sprintf('Class: %s, is not supported.', get_class($obj)));
50
    }
51
52
    /**
53
     * @param DataObject|ArrayData|SS_List $component
54
     * @param array $columns
55
     *
56
     * @return void
57
     * @throws Exception
58
     */
59
    protected function cannotIdentifyException($component, $columns = [])
60
    {
61
        if (!empty($columns)) {
62
            throw new Exception(
63
                sprintf(
64
                    'Cannot identify, "%s" from class "%s"',
65
                    implode('.', $columns),
66
                    get_class($component)
67
                )
68
            );
69
        }
70
    }
71
72
    /**
73
     * Resolves a Single field in the database.
74
     * @return mixed
75
     * @throws Exception
76
     */
77
    protected function resolveField()
78
    {
79
        $this->cannotIdentifyException($this->component, $this->columns);
80
        if ($this->columnName) {
81
            $method = $this->columnName;
82
            if (!method_exists($this->component, $method)) {
83
                throw new Exception(
84
                    sprintf('Method, "%s" not found on "%s"', $method, get_class($this->component))
85
                );
86
            }
87
            return $this->component->$method();
88
        }
89
        return $this->component->getValue();
90
    }
91
92
    /**
93
     * Resolves a DataObject value
94
     * @return mixed
95
     * @throws Exception
96
     */
97
    protected function resolveDataObject()
98
    {
99
        if (empty($this->columnName)) {
100
            return $this->component->toMap();
101
        }
102
        // Inspect component for element $relation
103
        if ($this->component->hasMethod($this->columnName)) {
104
            $relation = $this->columnName;
105
            return self::identify($this->component->$relation(), $this->columns);
106
        }
107
        // Inspect component has attribute
108
        if ($this->component->hasField($this->columnName)) {
109
            $data = $this->component->{$this->columnName};
110
            $dbObject = $this->component->dbObject($this->columnName);
111
            if ($dbObject && $this->columns) {
112
                $dbObject->setValue($data);
113
                return self::identify($dbObject, $this->columns);
114
            }
115
            return $data;
116
        }
117
        $this->cannotIdentifyException($this->component, [$this->columnName]);
118
    }
119
120
    /**
121
     * Resolves an ArrayData value
122
     * @return mixed
123
     * @throws Exception
124
     */
125
    public function resolveArrayData()
126
    {
127
        if (empty($this->columnName)) {
128
            return $this->component->toMap();
129
        }
130
        // Inspect component has attribute
131
        if ($this->component->hasField($this->columnName)) {
132
            return $this->component->{$this->columnName};
133
        }
134
        $this->cannotIdentifyException($this->component, [$this->columnName]);
135
    }
136
137
    /**
138
     * Resolves a DataList values
139
     * @return array|mixed
140
     * @throws Exception
141
     */
142
    public function resolveList()
143
    {
144
        if (empty($this->columnName)) {
145
            return $this->component->toNestedArray();
146
        }
147
        // Inspect $component for element $relation
148
        if ($this->component->hasMethod($this->columnName)) {
149
            $relation = $this->columnName;
150
            return self::identify($this->component->$relation(), $this->columns);
151
        }
152
        $data = [];
153
        array_unshift($this->columns, $this->columnName);
154
        foreach ($this->component as $component) {
155
            $data[] = self::identify($component, $this->columns);
156
        }
157
        return $data;
158
    }
159
}
160