JsonNode::encodeList()   C
last analyzed

Complexity

Conditions 8
Paths 16

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 20
cts 20
cp 1
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 19
nc 16
nop 1
crap 8
1
<?php
2
/**
3
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
25
namespace FacebookAds\Logger\CurlLogger;
26
27
final class JsonNode {
28
29
  /**
30
   * @var int
31
   */
32
  const INDENT_UNIT = 2;
33
34
  /**
35
   * @var int
36
   */
37
  const EXPLOSION_THRESHOLD = 78;
38
39
  /**
40
   * @var mixed
41
   */
42
  protected $value;
43
44
  /**
45
   * @var \ArrayObject
46
   */
47
  protected $children;
48
49
  /**
50
   * @param mixed $value
51
   * @return $this
52
   * @throws \InvalidArgumentException
53
   */
54 15
  public static function factory($value) {
55 15
    $object = new self();
56 15
    switch (true) {
57 15
      case is_object($value):
58 1
        $value = (array) $value;
59
        // fallthrough
60 15
      case is_array($value):
61 14
        foreach ($value as $key => $sub) {
62 10
          $object->getChildren()->offsetSet($key, self::factory($sub));
63 14
        }
64
        // fallthrough
65 15
      case is_null($value) || is_scalar($value):
66 14
        $object->setValue($value);
67 14
        break;
68 1
      default:
69 1
        throw new \InvalidArgumentException(
70 1
          gettype($value).' can\'t be encoded');
71 1
    }
72
73 14
    return $object;
74
  }
75
76 15
  public function __construct() {
77 15
    $this->children = new \ArrayObject();
78 15
  }
79
80
  /**
81
   * @return mixed
82
   */
83 13
  public function getValue() {
84 13
    return $this->value;
85
  }
86
87
  /**
88
   * @param mixed $value
89
   * @return $this
90
   */
91 14
  public function setValue($value) {
92 14
    $this->value = $value;
93
94 14
    return $this;
95
  }
96
97
  /**
98
   * @return \ArrayObject
99
   */
100 14
  public function getChildren() {
101 14
    return $this->children;
102
  }
103
104
  /**
105
   * @return int
106
   */
107 13
  public function getMaxTreeChildrenCount() {
108 13
    $max = $this->getChildren()->count();
109
110
    /** @var JsonNode $child */
111 13
    foreach ($this->getChildren() as $child) {
112 10
      $ith = $child->getMaxTreeChildrenCount();
113 10
      $max = $ith > $max ? $ith : $max;
114 13
    }
115
116 13
    return $max;
117
  }
118
119
  /**
120
   * @param int $indent
121
   * @return string
122
   */
123 13
  protected function getPadding($indent) {
124 13
    return str_repeat(' ', $indent * self::INDENT_UNIT);
125
  }
126
127
  /**
128
   * @return mixed
129
   */
130 10
  protected function getLastChildKey() {
131 10
    if ($this->getChildren()->count() === 0) {
132 1
      return null;
133
    }
134
135 9
    $copy = $this->getChildren()->getArrayCopy();
136 9
    end($copy);
137
138 9
    return key($copy);
139
  }
140
141
  /**
142
   * @param int $indent
143
   * @return string
144
   */
145 9
  protected function encodeList($indent) {
146 9
    $value = $this->getValue();
147 9
    if (empty($value) || (array_keys($value) === range(0, count($value) - 1))) {
148 3
      $is_map = false;
149 3
    } else {
150 7
      $is_map = true;
151
    }
152
153 9
    ++$indent;
154 9
    $last_key = $this->getLastChildKey();
155
156 9
    $buffer = ($is_map ? '{' : '[')."\n";
157
158
    /** @var JsonNode $child */
159 9
    foreach ($this->getChildren() as $key => $child) {
160 9
      $buffer .= sprintf(
161 9
        "%s%s%s%s\n",
162 9
        $this->getPadding($indent),
163 9
        $is_map ? sprintf("%s: ", json_encode($key)) : '',
164 9
        $child->encode($indent),
165 9
        $key === $last_key ? '' : ',');
166 9
    }
167
168 9
    --$indent;
169 9
    $buffer .= $this->getPadding($indent).($is_map ? '}' : ']');
170
171 9
    return $buffer;
172
  }
173
174
  /**
175
   * @param int $indent
176
   * @return string
177
   */
178 13
  public function encode($indent = 0) {
179 13
    $value = $this->getValue();
180 13
    if (is_array($value) || is_object($value)) {
181 13
      if ($this->getMaxTreeChildrenCount() > 2) {
182 8
        return $this->encodeList($indent);
183
      }
184
185 8
      $ugly = json_encode($value);
186 8
      $output_prediction = $this->getPadding($indent).$ugly;
187 8
      if (strlen($output_prediction) > self::EXPLOSION_THRESHOLD) {
188 2
        return $this->encodeList($indent);
189
      }
190
191 6
      return $ugly;
192
    }
193
194 9
    return json_encode($value);
195
  }
196
}
197