/** * @param $name * @param $value */ public function __set($name, $value) { if (in_array($name, ['prototype', 'properties'])) { return; } if (!isset($this->_ownProperties[$name]) && !\arc\prototype::isExtensible($this)) { return; } $valueIsSetterOrGetter = $this->_isGetterOrSetter($value); $propertyIsSetterOrGetter = isset($this->_ownProperties[$name]) ? $this->_isGetterOrSetter($this->_ownProperties[$name]) : false; if (\arc\prototype::isSealed($this) && $valueIsSetterOrGetter != $propertyIsSetterOrGetter) { return; } $changes = []; $changes['name'] = $name; $changes['object'] = $this; if (array_key_exists($name, $this->_ownProperties)) { $changes['type'] = 'update'; $changes['oldValue'] = $this->_ownProperties[$name]; } else { $changes['type'] = 'add'; } $clearcache = false; // get current value for $name, to check if it has a getter and/or a setter if (array_key_exists($name, $this->_ownProperties)) { $current = $this->_ownProperties[$name]; } else { $current = $this->_getPrototypeProperty($name); } if ($valueIsSetterOrGetter) { // reconfigure current property $clearcache = true; $this->_ownProperties[$name] = $value; unset($this->_staticMethods[$name]); } else { if (isset($current) && isset($current['set']) && is_callable($current['set'])) { // bindable setter found, use it, no need to set anything in _ownProperties $setter = \Closure::bind($current['set'], $this, $this); $setter($value); } else { if (isset($current) && isset($current[':set']) && is_callable($current[':set'])) { // nonbindable setter found $current[':set']($this, $value); } else { if (isset($current) && (isset($current['get']) && is_callable($current['get']) || isset($current[':get']) && is_callable($current[':get']))) { // there is only a getter, no setter, so ignore setting this property, its readonly. return null; } else { if (!array_key_exists($name, $this->_staticMethods)) { // bindable value, update _ownProperties, so clearcache as well $clearcache = true; $this->_ownProperties[$name] = $this->_bind($value); } else { // non bindable value, update _ownProperties, so clearcache as well $clearcache = true; $this->_ownProperties[$name] = $value; } } } } } if ($clearcache) { // purge prototype cache for this property - this will clear too much but cache will be filled again // clearing exactly the right entries from the cache will generally cost more performance than this unset(self::$properties[$name]); $observers = \arc\prototype::getObservers($this); if (isset($observers[$changes['type']])) { foreach ($observers[$changes['type']] as $observer) { $observer($changes); } } } }