Completed
Push — master ( 1857e6...d96bec )
by Joao
03:02
created

src/Model/ObjectHandler.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace ByJG\AnyDataset\Model;
4
5
use ByJG\AnyDataset\Repository\IteratorInterface;
6
use ByJG\Util\XmlUtil;
7
use DOMNode;
8
use Exception;
9
use InvalidArgumentException;
10
use ReflectionClass;
11
use ReflectionProperty;
12
use SimpleXMLElement;
13
use stdClass;
14
15
class ObjectHandler
16
{
17
18
    const CLASS_REFL = "ClassRefl";
19
    const CLASS_NAME = "ClassName";
20
    const CLASS_GETTER = "ClassGetter";
21
    const CLASS_PROPERTY_PATTERN = "ClassPropertyPattern";
22
    const CLASS_WRITE_EMPTY = "ClassWriteEmpty";
23
    const CLASS_DOC_TYPE = "ClassDocType";
24
    const CLASS_RDF_TYPE = "ClassRdfType";
25
    const CLASS_RDF_ABOUT = "ClassRdfAbout";
26
    const CLASS_DEFAULT_PREFIX = "ClassDefaultPrefix";
27
    const CLASS_IS_RDF = "ClassIsRDF";
28
    const CLASS_IGNORE_ALL_CLASS = "ClassIgnoreAllClass";
29
    const CLASS_NAMESPACE = "ClassNamespace";
30
    const CLASS_DONT_CREATE_NODE_CLASS = "ClassDontCreateClassNode";
31
    const NODE_REFS = "NodeRefs";
32
    const PROP_IGNORE = "PropIgnore";
33
    const PROP_NAME = "PropName";
34
    const PROP_ATTRIBUTE_OF = "PropAttributeOf";
35
    const PROP_IS_BLANK_NODE = "PropIsBlankNode";
36
    const PROP_IS_RESOURCE_URI = "PropIsResourceUri";
37
    const PROP_IS_CLASS_ATTR = "PropIsClassAttr";
38
    const PROP_DONT_CREATE_NODE = "PropDontCreateNode";
39
    const PROP_FORCE_NAME = "PropForceName";
40
    const PROP_VALUE = 'PropValue';
41
    const OBJECT_ARRAY_IGNORE_NODE = '__object__ignore';
42
    const OBJECT_ARRAY = '__object';
43
44
    protected $_model = null;
45
    protected $_config = "xmlnuke";
46
    protected $_forcePropName;
47
    protected $_current;
48
    protected $_node = null;
49
    protected $_parentArray = false;
50
    protected $_currentArray = false;
51
52
    /**
53
     *
54
     * @param DOMNode $current Current Dom Node
55
     * @param mixed $model Array or instance of object model
56
     * @param string $config The name of comment inspector
57
     * @param string $forcePropName force a name
58
     * @throws InvalidArgumentException
59
     */
60
    public function __construct($current, $model, $config = "xmlnuke", $forcePropName = "", $parentArray = false)
61
    {
62
        // Setup
63
        $this->_current = $current;
64
        $this->_config = $config;
65
        $this->_forcePropName = $forcePropName;
66
67
        // Define the parentArray
68
        $this->_parentArray = $parentArray;
69
70
        // Check the proper treatment
71
        if (is_array($model)) {
72
            $this->_model = (object) $model;
73
            $this->_currentArray = true;
74
75
            // Fix First Level non-associative arrays
76
            if (count(get_object_vars($this->_model)) == 0) {
77
                foreach ($model as $value) {
78
                    if (!is_object($value) && !is_array($value)) {
79
                        $this->_model->scalar[] = $value;
80
                    } else {
81
                        $this->_model->{ObjectHandler::OBJECT_ARRAY_IGNORE_NODE}[] = $value; // __object__ignore is a special name and it is not rendered
82
                    }
83
                }
84
            }
85
        } else if (is_object($model)) {
86
            $this->_model = $model;
87
        } else {
88
            throw new InvalidArgumentException('The model is not an object or an array');
89
        }
90
    }
91
92
    /**
93
     * Create a object model inside the "current node"
94
     * @return DOMNode
95
     */
96
    public function createObjectFromModel()
97
    {
98
        if ($this->_model instanceof IteratorInterface) {
99
            foreach ($this->_model as $singleRow) {
0 ignored issues
show
The expression $this->_model of type object<ByJG\AnyDataset\R...tory\IteratorInterface> is not traversable.
Loading history...
100
                XmlUtil::AddNodeFromNode($this->_current, $singleRow->getDomObject());
101
            }
102
            return $this->_current;
103
        }
104
105
        $classMeta = $this->getClassInfo();
106
107
        if ($classMeta[ObjectHandler::CLASS_IGNORE_ALL_CLASS]) {
108
            return $this->_current;
109
        }
110
111
112
        # Get the node names of this Class
113
        $node = $this->createClassNode($classMeta);
114
115
116
        #------------
117
        # Get all properties
118
        if ($this->_model instanceof stdClass) {
119
            $properties = get_object_vars($this->_model);
120
        } else {
121
            $properties = $classMeta[ObjectHandler::CLASS_REFL]->getProperties(ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE
122
                | ReflectionProperty::IS_PUBLIC);
123
        }
124
125
        $this->createPropertyNodes($node, $properties, $classMeta);
126
127
        return $node;
128
    }
129
130
    /**
131
     * Get the info of comment instance
132
     * @return array
133
     */
134
    protected function getClassInfo()
135
    {
136
        $classMeta = array();
137
138
        if (!$this->_model instanceof stdClass) {
139
            $class = new ReflectionClass($this->_model);
140
            preg_match_all('/@(?P<param>\S+)\s*(?P<value>\S+)?\r?\n/', $class->getDocComment(), $aux);
141
            $classAttributes = $this->adjustParams($aux);
142
143
            $classMeta[ObjectHandler::CLASS_REFL] = $class;
144
        } else {
145
            $classMeta[ObjectHandler::CLASS_REFL] = null;
146
            $classAttributes = array();
147
        }
148
149
        #------------
150
        # Define Class Attributes
151
        $classMeta[ObjectHandler::CLASS_NAME] = ($this->_forcePropName != "" ? $this->_forcePropName : (isset($classAttributes["$this->_config:nodename"])
152
                        ? $classAttributes["$this->_config:nodename"] : get_class($this->_model)));
153
        $classMeta[ObjectHandler::CLASS_GETTER] = isset($classAttributes["$this->_config:getter"]) ? $classAttributes["$this->_config:getter"]
154
                : "get";
155
        $classMeta[ObjectHandler::CLASS_PROPERTY_PATTERN] = isset($classAttributes["$this->_config:propertypattern"]) ? explode(',',
156
                $classAttributes["$this->_config:propertypattern"]) : array('/([^a-zA-Z0-9])/', '');
157
        $classMeta[ObjectHandler::CLASS_WRITE_EMPTY] = (isset($classAttributes["$this->_config:writeempty"]) ? $classAttributes["$this->_config:writeempty"]
158
                    : "false") == "true";
159
        $classMeta[ObjectHandler::CLASS_DOC_TYPE] = isset($classAttributes["$this->_config:doctype"]) ? strtolower($classAttributes["$this->_config:doctype"])
160
                : "xml";
161
        $classMeta[ObjectHandler::CLASS_RDF_TYPE] = $this->replaceVars($classMeta[ObjectHandler::CLASS_NAME],
162
            isset($classAttributes["$this->_config:rdftype"]) ? $classAttributes["$this->_config:rdftype"] : "{HOST}/rdf/class/{CLASS}");
163
        $classMeta[ObjectHandler::CLASS_RDF_ABOUT] = $this->replaceVars($classMeta[ObjectHandler::CLASS_NAME],
164
            isset($classAttributes["$this->_config:rdfabout"]) ? $classAttributes["$this->_config:rdfabout"] : "{HOST}/rdf/instance/{CLASS}/{GetID()}");
165
        $classMeta[ObjectHandler::CLASS_DEFAULT_PREFIX] = isset($classAttributes["$this->_config:defaultprefix"]) ? $classAttributes["$this->_config:defaultprefix"] . ":"
166
                : "";
167
        $classMeta[ObjectHandler::CLASS_IS_RDF] = ($classMeta[ObjectHandler::CLASS_DOC_TYPE] == "rdf");
168
        $classMeta[ObjectHandler::CLASS_IGNORE_ALL_CLASS] = array_key_exists("$this->_config:ignore", $classAttributes);
169
        $classMeta[ObjectHandler::CLASS_NAMESPACE] = isset($classAttributes["$this->_config:namespace"]) ? $classAttributes["$this->_config:namespace"]
170
                : "";
171
        $classMeta[ObjectHandler::CLASS_DONT_CREATE_NODE_CLASS] = array_key_exists("$this->_config:dontcreatenode",
172
            $classAttributes);
173
        if (!is_array($classMeta[ObjectHandler::CLASS_NAMESPACE]) && !empty($classMeta[ObjectHandler::CLASS_NAMESPACE]))
174
                $classMeta[ObjectHandler::CLASS_NAMESPACE] = array($classMeta[ObjectHandler::CLASS_NAMESPACE]);
175
176
        #----------
177
        # Node References
178
        $classMeta[ObjectHandler::NODE_REFS] = array();
179
180
        return $classMeta;
181
    }
182
183
    /**
184
     *
185
     * @param type $classMeta
186
     * @param type $prop
187
     * @param type $keyProp
188
     * @param type $this->_config
0 ignored issues
show
There is no parameter named $this->_config. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
189
     * @return null
190
     */
191
    protected function getPropInfo($classMeta, $prop, $keyProp)
192
    {
193
        $propMeta = array();
194
195
        $propName = ($prop instanceof ReflectionProperty ? $prop->getName() : $keyProp);
196
        $propAttributes = array();
197
198
        # Does nothing here
199
        if ($propName == "_propertyPattern") {
200
            return null;
201
        }
202
203
        # Determine where it located the Property Value --> Getter or inside the property
204
        if (!($prop instanceof ReflectionProperty) || $prop->isPublic()) {
205
            preg_match_all('/@(?<param>\S+)\s*(?<value>\S+)?\n/',
206
                ($prop instanceof ReflectionProperty ? $prop->getDocComment() : ""), $aux);
207
            $propAttributes = $this->adjustParams($aux);
208
            $propMeta[ObjectHandler::PROP_VALUE] = ($prop instanceof ReflectionProperty ? $prop->getValue($this->_model)
209
                        : $prop);
210
        } else {
211
            // Remove Prefix "_" from Property Name to find a value
212
            if ($propName[0] == "_") {
213
                $propName = substr($propName, 1);
214
            }
215
216
            $methodName = $classMeta[ObjectHandler::CLASS_GETTER] . ucfirst(preg_replace($classMeta[ObjectHandler::CLASS_PROPERTY_PATTERN][0],
217
                        $classMeta[ObjectHandler::CLASS_PROPERTY_PATTERN][1], $propName));
218
            if ($classMeta[ObjectHandler::CLASS_REFL]->hasMethod($methodName)) {
219
                $method = $classMeta[ObjectHandler::CLASS_REFL]->getMethod($methodName);
220
                preg_match_all('/@(?<param>\S+)\s*(?<value>\S+)?\r?\n/', $method->getDocComment(), $aux);
221
                $propAttributes = $this->adjustParams($aux);
222
                $propMeta[ObjectHandler::PROP_VALUE] = $method->invoke($this->_model, "");
223
            } else {
224
                return null;
225
            }
226
        }
227
228
229
        $propMeta[ObjectHandler::PROP_IGNORE] = array_key_exists("$this->_config:ignore", $propAttributes);
230
        $propMeta[ObjectHandler::PROP_NAME] = isset($propAttributes["$this->_config:nodename"]) ? $propAttributes["$this->_config:nodename"]
231
                : $propName;
232
        $propMeta[ObjectHandler::PROP_DONT_CREATE_NODE] = array_key_exists("$this->_config:dontcreatenode",
233
            $propAttributes);
234
        $propMeta[ObjectHandler::PROP_FORCE_NAME] = isset($propAttributes["$this->_config:dontcreatenode"]) ? $propAttributes["$this->_config:dontcreatenode"]
235
                : "";
236
        if (strpos($propMeta[ObjectHandler::PROP_NAME], ":") === false) {
237
            $propMeta[ObjectHandler::PROP_NAME] = $classMeta[ObjectHandler::CLASS_DEFAULT_PREFIX] . $propMeta[ObjectHandler::PROP_NAME];
238
        }
239
        if ($propMeta[ObjectHandler::PROP_NAME] == ObjectHandler::OBJECT_ARRAY_IGNORE_NODE) {
240
            $propMeta[ObjectHandler::PROP_DONT_CREATE_NODE] = true;
241
        }
242
        $propMeta[ObjectHandler::PROP_ATTRIBUTE_OF] = $classMeta[ObjectHandler::CLASS_IS_RDF] ? "" : (isset($propAttributes["$this->_config:isattributeof"])
243
                    ? $propAttributes["$this->_config:isattributeof"] : "");
244
        $propMeta[ObjectHandler::PROP_IS_BLANK_NODE] = $classMeta[ObjectHandler::CLASS_IS_RDF] ? (isset($propAttributes["$this->_config:isblanknode"])
245
                    ? $propAttributes["$this->_config:isblanknode"] : "") : "";
246
        $propMeta[ObjectHandler::PROP_IS_RESOURCE_URI] = $classMeta[ObjectHandler::CLASS_IS_RDF] && array_key_exists("$this->_config:isresourceuri",
247
                $propAttributes); // Valid Only Inside BlankNode
248
        $propMeta[ObjectHandler::PROP_IS_CLASS_ATTR] = $classMeta[ObjectHandler::CLASS_IS_RDF] ? false : array_key_exists("$this->_config:isclassattribute",
249
                $propAttributes);
250
251
252
253
        return $propMeta;
254
    }
255
256
    protected function createClassNode($classMeta)
257
    {
258
        #-----------
259
        # Setup NameSpaces
260
        if (is_array($classMeta[ObjectHandler::CLASS_NAMESPACE])) {
261
            foreach ($classMeta[ObjectHandler::CLASS_NAMESPACE] as $value) {
262
                $prefix = strtok($value, "!");
263
                $uri = str_replace($prefix . "!", "", $value);
264
                XmlUtil::AddNamespaceToDocument($this->_current, $prefix,
265
                    $this->replaceVars($classMeta[ObjectHandler::CLASS_NAME], $uri));
266
            }
267
        }
268
269
        #------------
270
        # Create Class Node
271
        if ($this->_model instanceof stdClass && $this->_parentArray) {
272
            $node = XmlUtil::CreateChild($this->_current, ObjectHandler::OBJECT_ARRAY);
273
        } else if ($classMeta[ObjectHandler::CLASS_DONT_CREATE_NODE_CLASS] || $this->_model instanceof stdClass) {
274
            $node = $this->_current;
275
        } else {
276
            if (!$classMeta[ObjectHandler::CLASS_IS_RDF]) {
277
                $node = XmlUtil::CreateChild($this->_current, $classMeta[ObjectHandler::CLASS_NAME]);
278
            } else {
279
                XmlUtil::AddNamespaceToDocument($this->_current, "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
280
                $node = XmlUtil::CreateChild($this->_current, "rdf:Description");
281
                XmlUtil::AddAttribute($node, "rdf:about", $classMeta[ObjectHandler::CLASS_RDF_ABOUT]);
282
                $nodeType = XmlUtil::CreateChild($node, "rdf:type");
283
                XmlUtil::AddAttribute($nodeType, "rdf:resource", $classMeta[ObjectHandler::CLASS_RDF_TYPE]);
284
            }
285
        }
286
287
        return $node;
288
    }
289
290
    protected function createPropertyNodes($node, $properties, $classMeta)
291
    {
292
        if (!is_null($properties)) {
293
            foreach ($properties as $keyProp => $prop) {
294
                # Define Properties
295
                $propMeta = $this->getPropInfo($classMeta, $prop, $keyProp);
296
297
                if ($propMeta[ObjectHandler::PROP_IGNORE]) {
298
                    continue;
299
                }
300
301
                # Process the Property Value
302
                $used = null;
303
304
                # ------------------------------------------------
305
                # Value is a OBJECT?
306
                if (is_object($propMeta[ObjectHandler::PROP_VALUE])) {
307
                    if ($propMeta[ObjectHandler::PROP_DONT_CREATE_NODE]) {
308
                        $nodeUsed = $node;
309
                    } else {
310
                        $nodeUsed = XmlUtil::CreateChild($node, $propMeta[ObjectHandler::PROP_NAME]);
311
                    }
312
313
                    $objHandler = new ObjectHandler($nodeUsed, $propMeta[ObjectHandler::PROP_VALUE], $this->_config,
314
                        $propMeta[ObjectHandler::PROP_FORCE_NAME]);
315
                    $used = $objHandler->createObjectFromModel();
316
                }
317
318
                # ------------------------------------------------
319
                # Value is an ARRAY?
320
                elseif (is_array($propMeta[ObjectHandler::PROP_VALUE])) {
321
                    // Check if the array is associative or dont.
322
                    $isAssoc = (bool) count(array_filter(array_keys($propMeta[ObjectHandler::PROP_VALUE]), 'is_string'));
323
                    $hasScalar = (bool) count(array_filter(array_values($propMeta[ObjectHandler::PROP_VALUE]),
324
                                function($val) {
325
                                return !(is_object($val) || is_array($val));
326
                            }));
327
328
                    $lazyCreate = false;
329
330
                    if ($propMeta[ObjectHandler::PROP_DONT_CREATE_NODE] || (!$isAssoc && $hasScalar)) {
331
                        $nodeUsed = $node;
332
                    } else if ((!$isAssoc && !$hasScalar)) {
333
                        $lazyCreate = true;    // Have to create the node every iteration
334
                    } else {
335
                        $nodeUsed = $used = XmlUtil::CreateChild($node, $propMeta[ObjectHandler::PROP_NAME]);
336
                    }
337
338
339
                    foreach ($propMeta[ObjectHandler::PROP_VALUE] as $keyAr => $valAr) {
340
                        if (
341
                            (!$isAssoc && $hasScalar)   # Is not an associative array and have scalar numbers in it.
342
                            || !(is_object($valAr) || is_array($valAr))    # The value is not an object and not is array
343
                            || (is_string($keyAr) && (is_object($valAr) || is_array($valAr))) # The key is string (associative array) and
344
                        # the valluris a object or array
345
                        ) {
346
                            $obj = new \stdClass;
347
                            $obj->{(is_string($keyAr) ? $keyAr : $propMeta[ObjectHandler::PROP_NAME])} = $valAr;
348
                            $this->_currentArray = false;
349
                        } else if ($lazyCreate) {
350
                            if (Is_null($used) && is_object($valAr)) { // If the child is an object there is no need to create every time the node.
351
                                $lazyCreate = false;
352
                            }
353
                            $nodeUsed = $used = XmlUtil::CreateChild($node, $propMeta[ObjectHandler::PROP_NAME]);
354
                            $obj = $valAr;
355
                        } else {
356
                            $obj = $valAr;
357
                        }
358
359
                        $objHandler = new ObjectHandler($nodeUsed, $obj, $this->_config,
0 ignored issues
show
The variable $nodeUsed does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
360
                            $propMeta[ObjectHandler::PROP_FORCE_NAME], $this->_currentArray);
361
                        $objHandler->createObjectFromModel();
362
                    }
363
                }
364
365
                # ------------------------------------------------
366
                # Value is a Single Value?
367
                else if (!empty($propMeta[ObjectHandler::PROP_VALUE])    // Some values are empty for PHP but need to be considered
368
                    || ($propMeta[ObjectHandler::PROP_VALUE] === 0) || ($propMeta[ObjectHandler::PROP_VALUE] === false) || ($propMeta[ObjectHandler::PROP_VALUE]
369
                    === '0') || ($classMeta[ObjectHandler::CLASS_WRITE_EMPTY])
370
                ) {
371
                    if ($propMeta[ObjectHandler::PROP_IS_CLASS_ATTR]) {
372
                        XmlUtil::AddAttribute($node, $propMeta[ObjectHandler::PROP_NAME],
373
                            $propMeta[ObjectHandler::PROP_VALUE]);
374
                    } elseif ($propMeta[ObjectHandler::PROP_IS_BLANK_NODE] != "") {
375
                        if (!array_key_exists($propMeta[ObjectHandler::PROP_IS_BLANK_NODE],
376
                                $classMeta[ObjectHandler::NODE_REFS])) {
377
                            $classMeta[ObjectHandler::NODE_REFS][$propMeta[ObjectHandler::PROP_IS_BLANK_NODE]] = XmlUtil::CreateChild($node,
378
                                    $propMeta[ObjectHandler::PROP_IS_BLANK_NODE]);
379
                            XmlUtil::AddAttribute($classMeta[ObjectHandler::NODE_REFS][$propMeta[ObjectHandler::PROP_IS_BLANK_NODE]],
380
                                "rdf:parseType", "Resource");
381
                        }
382
383
                        if ($propMeta[ObjectHandler::PROP_IS_RESOURCE_URI]) {
384
                            $blankNodeType = XmlUtil::CreateChild($classMeta[ObjectHandler::NODE_REFS][$propMeta[ObjectHandler::PROP_IS_BLANK_NODE]],
385
                                    "rdf:type");
386
                            XmlUtil::AddAttribute($blankNodeType, "rdf:resource", $propMeta[ObjectHandler::PROP_VALUE]);
387
                        } else {
388
                            XmlUtil::CreateChild($classMeta[ObjectHandler::NODE_REFS][$propMeta[ObjectHandler::PROP_IS_BLANK_NODE]],
389
                                $propMeta[ObjectHandler::PROP_NAME], $propMeta[ObjectHandler::PROP_VALUE]);
390
                        }
391
                    } elseif (($propMeta[ObjectHandler::PROP_ATTRIBUTE_OF] != "") && (array_key_exists($propMeta[ObjectHandler::PROP_ATTRIBUTE_OF],
392
                            $classMeta[ObjectHandler::NODE_REFS]))) {
393
                        XmlUtil::AddAttribute($classMeta[ObjectHandler::NODE_REFS][$propMeta[ObjectHandler::PROP_ATTRIBUTE_OF]],
394
                            $propMeta[ObjectHandler::PROP_NAME], $propMeta[ObjectHandler::PROP_VALUE]);
395
                    } elseif ((preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i',
396
                            $propMeta[ObjectHandler::PROP_VALUE])) && $classMeta[ObjectHandler::CLASS_IS_RDF]) {
397
                        $used = XmlUtil::CreateChild($node, $propMeta[ObjectHandler::PROP_NAME]);
398
                        XmlUtil::AddAttribute($used, "rdf:resource", $propMeta[ObjectHandler::PROP_VALUE]);
399
                    } elseif (is_bool($propMeta[ObjectHandler::PROP_VALUE])) {
400
                        $used = XmlUtil::CreateChild($node, $propMeta[ObjectHandler::PROP_NAME],
401
                                $propMeta[ObjectHandler::PROP_VALUE] ? 'true' : 'false');
402
                    } else {
403
                        $used = XmlUtil::CreateChild($node, $propMeta[ObjectHandler::PROP_NAME],
404
                                $propMeta[ObjectHandler::PROP_VALUE]);
405
                    }
406
                }
407
408
                # Save Reference for "isAttributeOf" attribute.
409
                if (!is_null($used)) {
410
                    $classMeta[ObjectHandler::NODE_REFS][$propMeta[ObjectHandler::PROP_NAME]] = $used;
411
                }
412
            }
413
        }
414
    }
415
416
    protected function replaceVars($name, $text)
417
    {
418
        # Host
419
        $port = isset($_SERVER["SERVER_PORT"]) ? $_SERVER["SERVER_PORT"] : 80;
420
        $httpHost = isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : 'localhost';
421
        $host = ($port == 443 ? "https://" : "http://") . $httpHost;
422
423
        # Replace Part One
424
        $text = preg_replace(array("/\{[hH][oO][sS][tT]\}/", "/\{[cC][lL][aA][sS][sS]\}/"), array($host, $name), $text);
425
426
        if (preg_match('/(\{(\S+)\})/', $text, $matches)) {
427
            $class = new ReflectionClass(get_class($this->_model));
428
            $method = str_replace("()", "", $matches[2]);
429
            $value = spl_object_hash($this->_model);
430
            if ($class->hasMethod($method)) {
431
                try {
432
                    $value = $this->_model->$method();
433
                } catch (Exception $ex) {
434
                    $value = "***$value***";
435
                }
436
            }
437
            $text = preg_replace('/(\{(\S+)\})/', $value, $text);
438
        }
439
440
        return $text;
441
    }
442
443
    protected function adjustParams($arr)
444
    {
445
        $count = count($arr[0]);
446
        $result = array();
447
448
        for ($i = 0; $i < $count; $i++) {
449
            $key = strtolower($arr["param"][$i]);
450
            $value = $arr["value"][$i];
451
452
            if (!array_key_exists($key, $result)) {
453
                $result[$key] = $value;
454
            } elseif (is_array($result[$key])) {
455
                $result[$key][] = $value;
456
            } else {
457
                $result[$key] = array($result[$key], $value);
458
            }
459
        }
460
461
        return $result;
462
    }
463
464
    protected static function mapArray(&$value, $key = null)
465
    {
466
        if ($value instanceof SimpleXMLElement) {
467
            $x = array();
468
            foreach ($value->children() as $k => $v) {
469
                $text = "" . $v;
470
                if ($text != "") {
471
                    $arText = array($text);
472
                } else {
473
                    $arText = array();
474
                }
475
                $x[$k][] = (array) $v + $arText;
476
            }
477
            $value = (array) $value->attributes() + $x;
478
        }
479
480
        // Fix empty arrays or with one element only.
481
        if (is_array($value)) {
482
            if (count($value) == 0) {
483
                $value = "";
484
            } elseif (count($value) == 1 && array_key_exists(0, $value)) {
485
                $value = $value[0];
486
            }
487
        }
488
489
        // If still as array, process it
490
        if (is_array($value)) {
491
            // Transform attributes
492
            if (array_key_exists("@attributes", $value)) {
493
                $attributes = array();
494
                foreach ($value["@attributes"] as $k => $v) {
495
                    $attributes["$k"] = $v;
496
                }
497
                $value = $attributes + $value;
498
                unset($value["@attributes"]);
499
            }
500
501
            // Fix empty arrays or with one element only.
502
            if (count($value) == 0) {
503
                $value = "";
504
            } else if (array_key_exists(0, $value) && count($value) == 1) {
505
                $value = $value[0];
506
            } else if (array_key_exists(0, $value) && !array_key_exists(1, $value)) {
507
                $value["_text"] = $value[0];
508
                unset($value[0]);
509
            }
510
511
            // If still an array, walk.
512
            if (is_array($value)) {
513
                array_walk($value, "ByJG\AnyDataset\Model\ObjectHandler::mapArray");
514
            }
515
        }
516
    }
517
518
    /**
519
     *
520
     * @param DOMNode $domnode
521
     * @param type $jsonFunction
522
     * @return type
523
     */
524
    public static function xml2json($domnode, $jsonFunction = "")
525
    {
526
        if (!($domnode instanceof DOMNode)) {
527
            throw new InvalidArgumentException("xml2json requires a \DOMNode descendant");
528
        }
529
530
        $xml = simplexml_import_dom($domnode);
531
532
        $pre = $pos = "";
533
        if (!empty($jsonFunction)) {
534
            $pre = "(";
535
            $pos = ")";
536
        }
537
538
        if ($xml->getName() == "xmlnuke") {
539
            $array = (array) $xml->children();
540
        } else {
541
            $array = (array) $xml;
542
        }
543
544
        array_walk($array, "ByJG\AnyDataset\Model\ObjectHandler::mapArray");
545
546
        // Check an special case from Xml
547
        if (isset($array[ObjectHandler::OBJECT_ARRAY])) {
548
            $json = json_encode($array[ObjectHandler::OBJECT_ARRAY]);
549
        } else {
550
            $json = json_encode($array);
551
        }
552
553
        return $jsonFunction . $pre . $json . $pos;
554
    }
555
}
556