Skip to content

Commit c44c8c5

Browse files
committed
Better internal value handling WIP
1 parent 3a2eeef commit c44c8c5

File tree

3 files changed

+141
-13
lines changed

3 files changed

+141
-13
lines changed

README.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,27 @@ My recommendation is to simply pick an instantiation method and use that for an
8686

8787
== Features
8888

89+
=== Storing Data
90+
91+
This is the primary feature of Brief.
92+
93+
Brief expects data in an array, but whether that array is keyed or numeric is up to you.
94+
(Or, use a language where arrays aren't as confusing.)
95+
96+
[source,php]
97+
----
98+
$keyed = Brief::make([
99+
'key' => 'value1',
100+
'key2' => 'value2',
101+
]);
102+
103+
$numeric = Brief::make([
104+
'number1',
105+
'number2',
106+
]);
107+
----
108+
109+
89110
=== Aliasing
90111

91112
You may find yourself in a situation where you want to have multiple keys that point to the same data.

src/Brief.php

Lines changed: 117 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,25 @@ protected function collapseAliasChain(string $alias, $chain = [])
224224
*/
225225
public function getAliasedKey(string $alias)
226226
{
227-
return $this->collapseAliasChain($alias);
227+
// Check alias for allowable keys
228+
if (false === $this::isKeyAllowed($alias)) {
229+
$this->log('ProtectedKey', 'This key is protected and cannot be used.',
230+
['key' => $alias, 'protected_keys' => self::$protected]);
231+
232+
return false;
233+
}
234+
235+
$authoritative = $this->collapseAliasChain($alias);
236+
237+
// Check resolved value for allowable keys
238+
if (false === $this::isKeyAllowed($authoritative)) {
239+
$this->log('ProtectedKey', 'This key is protected and cannot be used.',
240+
['key' => $authoritative, 'protected_keys' => self::$protected]);
241+
242+
return false;
243+
}
244+
245+
return $authoritative;
228246
}
229247

230248
/**
@@ -240,17 +258,17 @@ public function getAliasedKey(string $alias)
240258
*/
241259
protected function storeSingle($value, string $key = null, int $order = null): self
242260
{
261+
if (isset($this->aliases[$key])) {
262+
$key = $this->getAuthoritativeName($key) ?? $key;
263+
}
264+
243265
if (false === $this::isKeyAllowed($key)) {
244266
$this->log('ProtectedKey', 'This key is protected and cannot be used.',
245267
['key' => $key, 'protected_keys' => self::$protected]);
246268

247269
return $this;
248270
}
249271

250-
if (isset($this->aliases[$key])) {
251-
$key = $this->getAuthoritativeName($key) ?? $key;
252-
}
253-
254272
$this->store[$key] = [
255273
'value' => $value,
256274
'order' => $order
@@ -281,7 +299,6 @@ protected function store(array $values, int $order_start = 0)
281299
return $this;
282300
}
283301

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

314+
protected function getIntFromUnderscoreProp($key)
315+
{
316+
if (0 === strpos($key, '_') && is_numeric(substr($key, 1))) {
317+
return intval(substr($key, 1));
318+
}
319+
320+
return null;
321+
}
322+
/**
323+
* TODO: Make a `maybeSetByOrder` that allows us to try and set an ordered
324+
* item by numeric key using an underscore prop. Should first text to see if
325+
* there is an existing prop using the underscore string.
326+
*/
327+
328+
protected function maybeGetByOrder($key)
329+
{
330+
/**
331+
* Integers are not allowed as object properties, so here we make a
332+
* a way to easily access ordered data; by prefixing the order number
333+
* with an underscore, i.e. `$brief->_1`.
334+
*/
335+
$order = $this->getIntFromUnderscoreProp($key);
336+
if (null !== $order) {
337+
$value = $this->getByOrder($order);
338+
if (null !== $value) {
339+
return $value;
340+
}
341+
}
342+
343+
return false;
344+
}
345+
297346
/**
298347
* True if key has been set; false otherwise.
299348
*
@@ -303,7 +352,7 @@ public static function isKeyAllowed($key)
303352
*/
304353
public function __isset($name)
305354
{
306-
return in_array($name, array_keys($this->store));
355+
return $this->__get($name) ?? false;
307356
}
308357

309358
/**
@@ -315,7 +364,7 @@ public function __isset($name)
315364
*/
316365
public function __get($name)
317366
{
318-
return $this->getArgument($this->getAuthoritativeName($name));
367+
return $this->maybeGetByOrder($name) ?: $this->get($name);
319368
}
320369

321370
/**
@@ -330,7 +379,7 @@ public function __get($name)
330379
*/
331380
public function __set(string $name, $value)
332381
{
333-
$this->storeSingle($value, $this->getAuthoritativeName($name) ?? $name, $this->getIncrementedOrder());
382+
$this->set($name, $value);
334383
}
335384

336385
/**
@@ -340,13 +389,57 @@ public function __set(string $name, $value)
340389
*
341390
* @return mixed
342391
*/
343-
protected function getArgument($name)
392+
protected function getByKey($name)
344393
{
345394
return isset($this->store[$name])
346395
? $this->getValue($this->store[$name])
347396
: null;
348397
}
349398

399+
/**
400+
* Get a value from the Brief.
401+
*
402+
* If $key is an integer, it will get the data base on order, on
403+
* the assumption that this is a numeric array. If $key is a string,
404+
* they it will get the data based on the key.
405+
*
406+
* @param string|int $key
407+
* @return mixed|null
408+
*/
409+
public function get($key)
410+
{
411+
if (is_int($key)) {
412+
return $this->getByOrder($key);
413+
} elseif (is_string($key)) {
414+
return $this->getByKey($this->getAuthoritativeName($key));
415+
}
416+
417+
return null;
418+
}
419+
420+
/**
421+
* Store a value.
422+
*
423+
* If $key is an integer, then the value will be stored with that as
424+
* the order and the key name. If $key is a string, then the value will
425+
* be stored under that key, and its order will be the next in order.
426+
*
427+
* @param string|int $key
428+
* @param mixed $value
429+
*/
430+
public function set($key, $value)
431+
{
432+
if (is_int($key)) {
433+
$this->storeSingle($value, (string)$key, $key);
434+
} elseif (is_string($key)) {
435+
$this->storeSingle(
436+
$value,
437+
$this->getAuthoritativeName($key),
438+
$this->getIncrementedOrder()
439+
);
440+
}
441+
}
442+
350443
/**
351444
* This will get the authoritative name (either the key, or the key that
352445
* the passed alias points to).
@@ -482,6 +575,18 @@ public function getOrdered($fill = null)
482575
return array_column($this->getFilledOrdered($fill), 'value', 'order');
483576
}
484577

578+
/**
579+
* Get a value based on its order.
580+
*
581+
* @param integer $int
582+
* @return mixed
583+
*/
584+
public function getByOrder(int $int)
585+
{
586+
$ordered = $this->getOrdered();
587+
return $ordered[$int] ?? null;
588+
}
589+
485590
/**
486591
* Get all data in this Brief as a keyed array.
487592
*
@@ -557,7 +662,7 @@ public function find($keys)
557662
{
558663
// Be friendly
559664
if (is_string($keys)) {
560-
return $this->getArgument($keys);
665+
return $this->getByKey($keys);
561666
}
562667

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

573678
$get = array_shift($keys);
574679

575-
return $this->getArgument($get) ?: $this->find($keys);
680+
return $this->getByKey($get) ?: $this->find($keys);
576681
}
577682

578683
/**

tests/BriefTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ public function testAttemptingToUseProtectedKeyToDynamicallySetValueThrowsCorrec
6565
{
6666

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

7173
public function testAttemptingToPassNonViableInputLogsCorrectData(): void

0 commit comments

Comments
 (0)