Passed
Push — sheepy/rebase-latest ( 6694a6 )
by Simon
07:59
created

DataResolver::identify()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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