Gifari Industries - BD Cyber Security Team
Home
/
home
/
decohaslibrary
/
bist
/
wp-content
/
plugins
/
admin-menu-editor
/
customizables
/
Settings
/
✏️
Editing: AbstractStructSetting.php
<?php namespace YahnisElsts\AdminMenuEditor\Customizable\Settings; use YahnisElsts\AdminMenuEditor\Customizable\Storage; use YahnisElsts\AdminMenuEditor\Customizable\Storage\StorageInterface; abstract class AbstractStructSetting extends AbstractSetting implements \ArrayAccess, \IteratorAggregate { protected $dataType = 'map'; /** * @var array<string,AbstractSetting> */ protected $settings = []; /** * @var callable */ protected $childUpdateCallback; protected $childSubscriptionsAdded = false; protected $isInUpdateLoop = false; public function __construct($id, StorageInterface $store = null, $params = []) { //Minor optimization: Create the callback array once and reuse it for every child. $this->childUpdateCallback = [$this, 'notifyChildWasUpdated']; if ( $store === null ) { $store = new Storage\NullStorage(); } parent::__construct($id, $store, $params); } /** * @param \WP_Error $errors * @param array<string,mixed> $value * @return \WP_Error|array<string,mixed> */ public function validate($errors, $value, $stopOnFirstError = false) { if ( !is_array($value) ) { $errors->add('struct_value_invalid', 'Struct value must be an associative array'); return $errors; } $validatedValues = []; $foundErrors = false; foreach ($this->settings as $key => $setting) { if ( array_key_exists($key, $value) ) { $validity = $setting->validate($errors, $value[$key], $stopOnFirstError); if ( is_wp_error($validity) ) { $foundErrors = true; if ( $stopOnFirstError ) { break; } } else { $validatedValues[$key] = $validity; } } } if ( $foundErrors ) { return $errors; } else { return $validatedValues; } } public function update($validValue) { $this->isInUpdateLoop = true; $isSuccess = true; foreach ($this->settings as $key => $setting) { if ( array_key_exists($key, $validValue) ) { $isSuccess = $isSuccess && $setting->update($validValue[$key]); } } $this->isInUpdateLoop = false; $this->notifyUpdated(); return $isSuccess; } public function getValue($customDefault = []) { $result = is_array($customDefault) ? $customDefault : []; foreach ($this->settings as $key => $setting) { $result[$key] = $setting->getValue(); } return $result; } public function preview($unsafeValue, $errors = null) { if ( !is_array($unsafeValue) ) { return; } if ( $errors === null ) { $errors = new \WP_Error(); } foreach ($this->settings as $key => $setting) { if ( array_key_exists($key, $unsafeValue) ) { $setting->preview($unsafeValue[$key], $errors); } } } /** * @return array */ public function getDefaultValue() { return []; } public function canBeDeleted() { if ( $this->deleteWhenBlank ) { //In addition to other "blank" states, a struct can also be deleted //if it has no children or if all of its children can be deleted. $isDeletable = true; foreach ($this->settings as $setting) { if ( !$setting->canBeDeleted() ) { $isDeletable = false; break; } } if ( $isDeletable ) { return true; } } return parent::canBeDeleted(); } public function subscribe($callback) { parent::subscribe($callback); //Optimization: Listen for child updates only if we have subscribers. if ( !empty($this->updateSubscribers) && !$this->childSubscriptionsAdded ) { $this->childSubscriptionsAdded = true; foreach ($this->settings as $setting) { $setting->subscribe($this->childUpdateCallback); } } } /** * @internal This method needs to be public because it's used as a callback, * but you should not call it directly. * * @noinspection PhpUnusedParameterInspection In the current implementation, * we don't care which specific child was updated, only that one was. * * @param AbstractSetting $childSetting * @return void */ public function notifyChildWasUpdated(AbstractSetting $childSetting) { //If we're inside the foreach loop in update(), we don't need to notify //our subscribers here - update() will do it after the loop. //Also, we currently don't support recursive notifications, so if a child //is updated while we're sending notifications, we'll just ignore it. if ( $this->isInUpdateLoop || $this->isNotifyingSubscribers ) { return; } //Optimization: Multiple children can be updated at the same time, and //it would be inefficient to notify the parent's subscribers every time. //Instead, we'll put the parent in a queue. The code performing the update //should send pending notifications when it's done. static::getNotificationQueue()->enqueue($this); } /** * @param string $key * @return AbstractSetting|null */ public function getChild($key) { if ( array_key_exists($key, $this->settings) ) { return $this->settings[$key]; } return null; } public function getChildValue($childSettingKey, $defaultValue = null) { if ( array_key_exists($childSettingKey, $this->settings) ) { return $this->settings[$childSettingKey]->getValue($defaultValue); } return $defaultValue; } public function makeChildId($childKey) { return $this->id . '.' . $childKey; } /** * Create a child setting of the specified type. * * @param string $childKey * @param class-string<AbstractSetting> $className * @param ...$constructorParams * @return AbstractSetting */ protected function createChild($childKey, $className, ...$constructorParams) { $child = new $className( $this->makeChildId($childKey), $this->store->buildSlot($childKey), ...$constructorParams ); if ( $this->shouldEnablePostMessageForChildren() ) { $child->enablePostMessageSupport(); } //Children inherit the parent's tags. $child->addTags(...$this->tags); $this->registerChild($childKey, $child); return $child; } protected function registerChild($childKey, AbstractSetting $child) { $this->settings[$childKey] = $child; if ( $this->childSubscriptionsAdded ) { $child->subscribe($this->childUpdateCallback); } } public function enablePostMessageSupport() { parent::enablePostMessageSupport(); if ( $this->shouldEnablePostMessageForChildren() ) { foreach ($this->settings as $setting) { $setting->enablePostMessageSupport(); } } } protected function shouldEnablePostMessageForChildren() { return $this->supportsPostMessage; } /** @noinspection PhpLanguageLevelInspection */ #[\ReturnTypeWillChange] public function offsetExists($offset) { return array_key_exists($offset, $this->settings); } /** * @param string $offset * @return AbstractSetting|null * @noinspection PhpLanguageLevelInspection */ #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->getChild($offset); } /** @noinspection PhpLanguageLevelInspection */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new \LogicException( 'Cannot add or replace a child of a struct. The setting list is read-only.' ); } /** @noinspection PhpLanguageLevelInspection */ #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new \LogicException( 'Cannot remove a child of a struct. The setting list is read-only.' ); } /** @noinspection PhpLanguageLevelInspection */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->settings); } }
💾 Save
❌ Cancel