Completed
Push — master ( b59d95...c30b72 )
by Robbie
10s
created

JSONDataFormatter::convertArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\RestfulServer\DataFormatter;
4
5
use SilverStripe\View\ArrayData;
6
use SilverStripe\Core\Convert;
7
use SilverStripe\RestfulServer\DataFormatter;
8
use SilverStripe\ORM\DataObjectInterface;
9
use SilverStripe\Control\Director;
10
use SilverStripe\ORM\SS_List;
11
12
/**
13
 * Formats a DataObject's member fields into a JSON string
14
 */
15
class JSONDataFormatter extends DataFormatter
16
{
17
    /**
18
     * @config
19
     * @todo pass this from the API to the data formatter somehow
20
     */
21
    private static $api_base = "api/v1/";
22
23
    protected $outputContentType = 'application/json';
24
25
    /**
26
     * @return array
27
     */
28
    public function supportedExtensions()
29
    {
30
        return array(
31
            'json',
32
            'js'
33
        );
34
    }
35
36
    /**
37
     * @return array
38
     */
39
    public function supportedMimeTypes()
40
    {
41
        return array(
42
            'application/json',
43
            'text/x-json'
44
        );
45
    }
46
47
    /**
48
     * @param $array
49
     * @return string
50
     */
51
    public function convertArray($array)
52
    {
53
        return Convert::array2json($array);
54
    }
55
56
    /**
57
     * Generate a JSON representation of the given {@link DataObject}.
0 ignored issues
show
Bug introduced by
The type SilverStripe\RestfulServ...ataFormatter\DataObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
58
     *
59
     * @param DataObject $obj   The object
60
     * @param Array $fields     If supplied, only fields in the list will be returned
61
     * @param $relations        Not used
0 ignored issues
show
Bug introduced by
The type SilverStripe\RestfulServer\DataFormatter\Not was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
62
     * @return String JSON
63
     */
64
    public function convertDataObject(DataObjectInterface $obj, $fields = null, $relations = null)
65
    {
66
        return Convert::array2json($this->convertDataObjectToJSONObject($obj, $fields, $relations));
0 ignored issues
show
Bug introduced by
$this->convertDataObject...j, $fields, $relations) of type SilverStripe\RestfulServ...rmatter\EmptyJSONObject is incompatible with the type array expected by parameter $val of SilverStripe\Core\Convert::array2json(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

66
        return Convert::array2json(/** @scrutinizer ignore-type */ $this->convertDataObjectToJSONObject($obj, $fields, $relations));
Loading history...
67
    }
68
69
    /**
70
     * Internal function to do the conversion of a single data object. It builds an empty object and dynamically
71
     * adds the properties it needs to it. If it's done as a nested array, json_encode or equivalent won't use
72
     * JSON object notation { ... }.
73
     * @param DataObjectInterface $obj
74
     * @param  $fields
75
     * @param  $relations
76
     * @return EmptyJSONObject
0 ignored issues
show
Bug introduced by
The type SilverStripe\RestfulServ...rmatter\EmptyJSONObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
77
     */
78
    public function convertDataObjectToJSONObject(DataObjectInterface $obj, $fields = null, $relations = null)
79
    {
80
        $className = get_class($obj);
81
        $id = $obj->ID;
82
83
        $serobj = ArrayData::array_to_object();
84
85
        foreach ($this->getFieldsForObj($obj) as $fieldName => $fieldType) {
86
            // Field filtering
87
            if ($fields && !in_array($fieldName, $fields)) {
88
                continue;
89
            }
90
91
            $fieldValue = $obj->obj($fieldName)->forTemplate();
92
            $serobj->$fieldName = $fieldValue;
93
        }
94
95
        if ($this->relationDepth > 0) {
96
            foreach ($obj->hasOne() as $relName => $relClass) {
97
                if (!singleton($relClass)->stat('api_access')) {
98
                    continue;
99
                }
100
101
                // Field filtering
102
                if ($fields && !in_array($relName, $fields)) {
103
                    continue;
104
                }
105
                if ($this->customRelations && !in_array($relName, $this->customRelations)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->customRelations of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
106
                    continue;
107
                }
108
109
                $fieldName = $relName . 'ID';
110
                if ($obj->$fieldName) {
111
                    $href = Director::absoluteURL($this->config()->api_base . "$relClass/" . $obj->$fieldName);
112
                } else {
113
                    $href = Director::absoluteURL($this->config()->api_base . "$className/$id/$relName");
114
                }
115
                $serobj->$relName = ArrayData::array_to_object(array(
116
                    "className" => $relClass,
117
                    "href" => "$href.json",
118
                    "id" => $obj->$fieldName
119
                ));
120
            }
121
122
            foreach ($obj->hasMany() + $obj->manyMany() as $relName => $relClass) {
123
                //remove dot notation from relation names
124
                $parts = explode('.', $relClass);
125
                $relClass = array_shift($parts);
126
127
                if (!singleton($relClass)->stat('api_access')) {
128
                    continue;
129
                }
130
131
                // Field filtering
132
                if ($fields && !in_array($relName, $fields)) {
133
                    continue;
134
                }
135
                if ($this->customRelations && !in_array($relName, $this->customRelations)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->customRelations of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
136
                    continue;
137
                }
138
139
                $innerParts = array();
140
                $items = $obj->$relName();
141
                foreach ($items as $item) {
142
                    //$href = Director::absoluteURL($this->config()->api_base . "$className/$id/$relName/$item->ID");
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
143
                    $href = Director::absoluteURL($this->config()->api_base . "$relClass/$item->ID");
144
                    $innerParts[] = ArrayData::array_to_object(array(
145
                        "className" => $relClass,
146
                        "href" => "$href.json",
147
                        "id" => $item->ID
148
                    ));
149
                }
150
                $serobj->$relName = $innerParts;
151
            }
152
        }
153
154
        return $serobj;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $serobj returns the type stdClass which is incompatible with the documented return type SilverStripe\RestfulServ...rmatter\EmptyJSONObject.
Loading history...
155
    }
156
157
    /**
158
     * Generate a JSON representation of the given {@link SS_List}.
159
     *
160
     * @param SS_List $set
161
     * @return String XML
162
     */
163
    public function convertDataObjectSet(SS_List $set, $fields = null)
164
    {
165
        $items = array();
166
        foreach ($set as $do) {
167
            if (!$do->canView()) {
168
                continue;
169
            }
170
            $items[] = $this->convertDataObjectToJSONObject($do, $fields);
171
        }
172
173
        $serobj = ArrayData::array_to_object(array(
174
            "totalSize" => (is_numeric($this->totalSize)) ? $this->totalSize : null,
0 ignored issues
show
introduced by
The condition is_numeric($this->totalSize) can never be false.
Loading history...
175
            "items" => $items
176
        ));
177
178
        return Convert::array2json($serobj);
0 ignored issues
show
Bug introduced by
$serobj of type stdClass is incompatible with the type array expected by parameter $val of SilverStripe\Core\Convert::array2json(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

178
        return Convert::array2json(/** @scrutinizer ignore-type */ $serobj);
Loading history...
179
    }
180
181
    /**
182
     * @param string $strData
183
     * @return array|bool|void
184
     */
185
    public function convertStringToArray($strData)
186
    {
187
        return Convert::json2array($strData);
188
    }
189
}
190