Skip to content

Commit

Permalink
Better internal value handling WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
alwaysblank committed Dec 22, 2019
1 parent 3a2eeef commit c44c8c5
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 13 deletions.
21 changes: 21 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,27 @@ My recommendation is to simply pick an instantiation method and use that for an

== Features

=== Storing Data

This is the primary feature of Brief.

Brief expects data in an array, but whether that array is keyed or numeric is up to you.
(Or, use a language where arrays aren't as confusing.)

[source,php]
----
$keyed = Brief::make([
'key' => 'value1',
'key2' => 'value2',
]);
$numeric = Brief::make([
'number1',
'number2',
]);
----


=== Aliasing

You may find yourself in a situation where you want to have multiple keys that point to the same data.
Expand Down
129 changes: 117 additions & 12 deletions src/Brief.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,25 @@ protected function collapseAliasChain(string $alias, $chain = [])
*/
public function getAliasedKey(string $alias)
{
return $this->collapseAliasChain($alias);
// Check alias for allowable keys
if (false === $this::isKeyAllowed($alias)) {
$this->log('ProtectedKey', 'This key is protected and cannot be used.',
['key' => $alias, 'protected_keys' => self::$protected]);

return false;
}

$authoritative = $this->collapseAliasChain($alias);

// Check resolved value for allowable keys
if (false === $this::isKeyAllowed($authoritative)) {
$this->log('ProtectedKey', 'This key is protected and cannot be used.',
['key' => $authoritative, 'protected_keys' => self::$protected]);

return false;
}

return $authoritative;
}

/**
Expand All @@ -240,17 +258,17 @@ public function getAliasedKey(string $alias)
*/
protected function storeSingle($value, string $key = null, int $order = null): self
{
if (isset($this->aliases[$key])) {
$key = $this->getAuthoritativeName($key) ?? $key;
}

if (false === $this::isKeyAllowed($key)) {
$this->log('ProtectedKey', 'This key is protected and cannot be used.',
['key' => $key, 'protected_keys' => self::$protected]);

return $this;
}

if (isset($this->aliases[$key])) {
$key = $this->getAuthoritativeName($key) ?? $key;
}

$this->store[$key] = [
'value' => $value,
'order' => $order
Expand Down Expand Up @@ -281,7 +299,6 @@ protected function store(array $values, int $order_start = 0)
return $this;
}


/**
* Checks an individual key to see if it is allowed.
*
Expand All @@ -294,6 +311,38 @@ public static function isKeyAllowed($key)
return ! in_array($key, self::$protected);
}

protected function getIntFromUnderscoreProp($key)
{
if (0 === strpos($key, '_') && is_numeric(substr($key, 1))) {
return intval(substr($key, 1));
}

return null;
}
/**
* TODO: Make a `maybeSetByOrder` that allows us to try and set an ordered
* item by numeric key using an underscore prop. Should first text to see if
* there is an existing prop using the underscore string.
*/

protected function maybeGetByOrder($key)
{
/**
* Integers are not allowed as object properties, so here we make a
* a way to easily access ordered data; by prefixing the order number
* with an underscore, i.e. `$brief->_1`.
*/
$order = $this->getIntFromUnderscoreProp($key);
if (null !== $order) {
$value = $this->getByOrder($order);
if (null !== $value) {
return $value;
}
}

return false;
}

/**
* True if key has been set; false otherwise.
*
Expand All @@ -303,7 +352,7 @@ public static function isKeyAllowed($key)
*/
public function __isset($name)
{
return in_array($name, array_keys($this->store));
return $this->__get($name) ?? false;
}

/**
Expand All @@ -315,7 +364,7 @@ public function __isset($name)
*/
public function __get($name)
{
return $this->getArgument($this->getAuthoritativeName($name));
return $this->maybeGetByOrder($name) ?: $this->get($name);
}

/**
Expand All @@ -330,7 +379,7 @@ public function __get($name)
*/
public function __set(string $name, $value)
{
$this->storeSingle($value, $this->getAuthoritativeName($name) ?? $name, $this->getIncrementedOrder());
$this->set($name, $value);
}

/**
Expand All @@ -340,13 +389,57 @@ public function __set(string $name, $value)
*
* @return mixed
*/
protected function getArgument($name)
protected function getByKey($name)
{
return isset($this->store[$name])
? $this->getValue($this->store[$name])
: null;
}

/**
* Get a value from the Brief.
*
* If $key is an integer, it will get the data base on order, on
* the assumption that this is a numeric array. If $key is a string,
* they it will get the data based on the key.
*
* @param string|int $key
* @return mixed|null
*/
public function get($key)
{
if (is_int($key)) {
return $this->getByOrder($key);
} elseif (is_string($key)) {
return $this->getByKey($this->getAuthoritativeName($key));
}

return null;
}

/**
* Store a value.
*
* If $key is an integer, then the value will be stored with that as
* the order and the key name. If $key is a string, then the value will
* be stored under that key, and its order will be the next in order.
*
* @param string|int $key
* @param mixed $value
*/
public function set($key, $value)
{
if (is_int($key)) {
$this->storeSingle($value, (string)$key, $key);
} elseif (is_string($key)) {
$this->storeSingle(
$value,
$this->getAuthoritativeName($key),
$this->getIncrementedOrder()
);
}
}

/**
* This will get the authoritative name (either the key, or the key that
* the passed alias points to).
Expand Down Expand Up @@ -482,6 +575,18 @@ public function getOrdered($fill = null)
return array_column($this->getFilledOrdered($fill), 'value', 'order');
}

/**
* Get a value based on its order.
*
* @param integer $int
* @return mixed
*/
public function getByOrder(int $int)
{
$ordered = $this->getOrdered();
return $ordered[$int] ?? null;
}

/**
* Get all data in this Brief as a keyed array.
*
Expand Down Expand Up @@ -557,7 +662,7 @@ public function find($keys)
{
// Be friendly
if (is_string($keys)) {
return $this->getArgument($keys);
return $this->getByKey($keys);
}

// ...Otherwise, it has to be an array
Expand All @@ -572,7 +677,7 @@ public function find($keys)

$get = array_shift($keys);

return $this->getArgument($get) ?: $this->find($keys);
return $this->getByKey($get) ?: $this->find($keys);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion tests/BriefTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ public function testAttemptingToUseProtectedKeyToDynamicallySetValueThrowsCorrec
{

$this->expectOutputRegex('/ERR: ProtectedKey :: This key is protected and cannot be used. ::.*/ms');
Brief::make([], ['logger' => true])->protected = 'value';
$Brief = Brief::make([], ['logger' => true]);
$Brief->protected = 'value';
var_dump($Brief);
}

public function testAttemptingToPassNonViableInputLogsCorrectData(): void
Expand Down

0 comments on commit c44c8c5

Please sign in to comment.