Issues (16)

src/Chips/Binding.php (3 issues)

Labels
1
<?php
2
/**
3
 * Options binding
4
 * User: moyo
5
 * Date: 18/10/2017
6
 * Time: 2:23 PM
7
 */
8
9
namespace Carno\Config\Chips;
10
11
use ReflectionClass;
12
use ReflectionException;
13
use ReflectionProperty;
14
15
trait Binding
16
{
17
    /**
18
     * @var ReflectionProperty[]
19
     */
20
    private $references = [];
21
22
    /**
23
     * @var array
24
     */
25
    private $bound = [];
26
27
    /**
28
     * @param object $options
29
     * @param array $map
30
     * @return object|mixed
31
     */
32
    public function bind($options, array $map)
33
    {
34
        $this->unbind($options);
35
36
        $this->bindPTKeys($options, '', $map);
37
38
        return $options;
39
    }
40
41
    /**
42
     * @param object $options
43
     * @return bool
44
     */
45
    public function unbind($options) : bool
46
    {
47
        if ($wss = $this->bound[$oid = spl_object_hash($options)] ?? []) {
48
            unset($this->bound[$oid]);
49
            unset($this->references[$oid]);
50
            foreach ($wss as $wid) {
51
                $this->unwatch($wid);
0 ignored issues
show
It seems like unwatch() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

51
                $this->/** @scrutinizer ignore-call */ 
52
                       unwatch($wid);
Loading history...
52
            }
53
            return true;
54
        }
55
        return false;
56
    }
57
58
    /**
59
     * @param object $options
60
     * @param string $prefix
61
     * @param array $map
62
     */
63
    private function bindPTKeys($options, string $prefix, array $map) : void
64
    {
65
        $prefix && $prefix .= '/';
66
        foreach ($map as $cKey => $pName) {
67
            if (is_array($pName)) {
68
                $this->bindPTKeys($options, $prefix . $cKey, $pName);
69
            } else {
70
                $this->bound[spl_object_hash($options)][] =
71
                    $this->watching(
0 ignored issues
show
It seems like watching() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

71
                /** @scrutinizer ignore-call */ 
72
                $this->bound[spl_object_hash($options)][] =
Loading history...
72
                        $prefix . $cKey,
73
                        function ($value) use ($options, $pName) {
74
                            $this->syncPTValue($options, $pName, $value);
75
                        }
76
                    )
77
                ;
78
            }
79
        }
80
    }
81
82
    /**
83
     * @param object $options
84
     * @param string $name
85
     * @param mixed $value
86
     * @throws ReflectionException
87
     */
88
    private function syncPTValue($options, string $name, $value) : void
89
    {
90
        $oid = spl_object_hash($options);
91
92
        /**
93
         * @var ReflectionProperty $property
94
         */
95
96
        $property =
97
            $this->references[$oid][$name] ?? (
98
                $this->references[$oid][$name] = (
99
                    (new ReflectionClass(get_class($options)))->getProperty($name) ?: null
100
                )
101
            )
102
        ;
103
104
        if ($property) {
0 ignored issues
show
$property is of type ReflectionProperty, thus it always evaluated to true.
Loading history...
105
            $property->isPublic() || $property->setAccessible(true);
106
            is_null($value) || $property->setValue($options, $value);
107
        }
108
    }
109
}
110