Completed
Branch EDTR/master (83b47e)
by
unknown
25:37 queued 16:41
created

JsonDataNodeHandler::initializeDataNodes()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 2
nop 2
dl 0
loc 25
rs 8.8977
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\json;
4
5
use DomainException;
6
use EE_Registry;
7
8
/**
9
 * Class JsonDataNodeHandler
10
 * registers JsonDataNode objects,
11
 * compiles data from them into a single JSON encoded string,
12
 * and prints that to the DOM as an inline script for the specified script handle
13
 *
14
 * @package EventEspresso\core\services\json
15
 * @author  Brent Christensen
16
 * @since   $VID:$
17
 */
18
class JsonDataNodeHandler
19
{
20
21
    /**
22
     * @var PrimaryJsonDataNode $primary_data_node
23
     */
24
    private $primary_data_node;
25
26
    /**
27
     * @var JsonDataNodeValidator $validator
28
     */
29
    private $validator;
30
31
32
    /**
33
     * JsonDataNodeHandler constructor.
34
     *
35
     * @param JsonDataNodeValidator $validator
36
     */
37
    public function __construct(JsonDataNodeValidator $validator)
38
    {
39
        $this->validator = $validator;
40
    }
41
42
43
    /**
44
     * @param JsonDataNode $data_node
45
     * @throws DomainException
46
     */
47
    public function addDataNode(JsonDataNode $data_node)
48
    {
49
        if ($data_node->isNotInitialized()) {
50
            $this->validatePrimaryDataNode($data_node);
51
            $this->primary_data_node->addDataNode($data_node);
52
        }
53
    }
54
55
56
    /**
57
     * @param PrimaryJsonDataNode $primary_data_node
58
     */
59
    public function setPrimaryDataNode(PrimaryJsonDataNode $primary_data_node)
60
    {
61
        $this->primary_data_node = $primary_data_node;
62
    }
63
64
65
    /**
66
     * @param JsonDataNode $data_node
67
     * @param int                $depth
68
     * @return mixed
69
     * @since $VID:$
70
     */
71
    private function initializeDataNodes(JsonDataNode $data_node, $depth = 0)
72
    {
73
        $depth++;
74
        $data = [];
75
        // initialize the data node if not done already
76
        if ($data_node->isNotInitialized()) {
77
            $data_node->initialize();
78
            // grab the data node's data array
79
            $data_node_data = $data_node->data();
80
            foreach ($data_node_data as $child_node_name => $child_node) {
81
                // don't parse node if it's the primary, OR if depth has exceeded wp_json_encode() limit
82
                if ($child_node instanceof PrimaryJsonDataNode || $depth > 512) {
83
                    continue;
84
                }
85
                if ($child_node instanceof JsonDataNode) {
86
                    // feed data node back into this function
87
                    $data[ $child_node_name ] = $this->initializeDataNodes($child_node, $depth);
88
                } else {
89
                    // or assign data directly
90
                    $data[ $child_node_name ] = $child_node;
91
                }
92
            }
93
        }
94
        return $data;
95
    }
96
97
98
    /**
99
     * @throws DomainException
100
     * @since $VID:$
101
     */
102
    public function printDataNode()
103
    {
104
        // validate that the domain, node name, and target script are set
105
        $domain = $this->primary_data_node->domain();
106
        $node_name = $this->primary_data_node->nodeName();
107
        $target_script = $this->primary_data_node->targetScript();
108
        $data_valid =  $this->validator->validateCriticalProperty($domain, 'domain route', false)
109
                       && $this->validator->validateCriticalProperty($node_name, 'node name', false)
110
                       && $this->validator->validateCriticalProperty($target_script, 'target script', false);
111
        if (! $data_valid) {
112
            return;
113
        }
114
        // initialize and parse data from primary data node
115
        $data = $this->initializeDataNodes($this->primary_data_node);
116
        // this prepends the current domain "use case" to the front of the array
117
        $data = ['domain' => $domain] + $data;
118
        // add legacy i18n strings
119
        $data['eei18n'] = EE_Registry::$i18n_js_strings;
120
        // and finally JSON encode the data and attach to the target script
121
        $data = json_encode($data);
122
        wp_add_inline_script($target_script, "var {$node_name}={$data};", 'before');
123
    }
124
125
126
    /**
127
     * @param JsonDataNode $data_node
128
     * @throws DomainException
129
     */
130
    private function validatePrimaryDataNode(JsonDataNode $data_node)
131
    {
132
        // set primary data node if that's what the incoming node is
133
        if ($data_node instanceof PrimaryJsonDataNode) {
134
            $this->setPrimaryDataNode($data_node);
135
        }
136
        // and don't allow other nodes to be set until a primary is set
137
        if (! $this->primary_data_node instanceof PrimaryJsonDataNode) {
138
            throw new DomainException(
139
                esc_html__(
140
                    'A PrimaryJsonDataNode needs to be set before data nodes can be added.',
141
                    'event_espresso'
142
                )
143
            );
144
        }
145
    }
146
}
147