11<?php
22/**
3- * Common abstract for the common classes package (last modified: 2024.09.20 ).
3+ * Common abstract for the common classes package (last modified: 2026.03.17 ).
44 *
55 * This file is a part of the "common classes package", utilised by a number of
66 * packages and projects, including CIDRAM and phpMussel.
@@ -20,7 +20,7 @@ abstract class CommonAbstract
2020 * @var string Common Classes Package tag/release version.
2121 * @link https://github.com/Maikuolan/Common/tags
2222 */
23- public const VERSION = '2.12.3 ' ;
23+ public const VERSION = '2.16.0 ' ;
2424
2525 /**
2626 * Traverse data path.
@@ -33,32 +33,73 @@ abstract class CommonAbstract
3333 */
3434 public function dataTraverse (&$ Data , $ Path = [], bool $ AllowNonScalar = false , bool $ AllowMethodCalls = false )
3535 {
36- if (!is_array ($ Path )) {
37- $ Path = preg_split ('~(?<! \\\\) \\.~ ' , $ Path ) ?: [];
36+ if (!\ is_array ($ Path )) {
37+ $ Path = \ preg_split ('~(?<! \\\\) \\.~ ' , $ Path ) ?: [];
3838 }
39- $ Segment = array_shift ($ Path );
40- if ($ Segment === null || strlen ($ Segment ) === 0 ) {
41- return $ AllowNonScalar || is_scalar ($ Data ) ? $ Data : '' ;
39+ $ Segment = \ array_shift ($ Path );
40+ if ($ Segment === null || \ strlen ($ Segment ) === 0 ) {
41+ return $ AllowNonScalar || \ is_scalar ($ Data ) ? $ Data : '' ;
4242 }
43- $ Segment = str_replace ('\. ' , '. ' , $ Segment );
44- if (is_array ($ Data )) {
43+ $ Segment = \str_replace ('\. ' , '. ' , $ Segment );
44+ if ($ Data instanceof \Maikuolan \Common \LazyArray) {
45+ $ Data ->trigger ();
46+ $ Data = $ Data ->Data ;
47+ }
48+ if (\is_array ($ Data )) {
49+ if (\preg_match ('~^(?:keys|flip|pop|shift) \\( \\)$~i ' , $ Segment )) {
50+ $ Segment = 'array_ ' . \substr ($ Segment , 0 , -2 );
51+ $ Working = $ Segment ($ Data );
52+ return $ this ->dataTraverse ($ Working , $ Path , $ AllowNonScalar , $ AllowMethodCalls );
53+ }
4554 return isset ($ Data [$ Segment ]) ? $ this ->dataTraverse ($ Data [$ Segment ], $ Path , $ AllowNonScalar , $ AllowMethodCalls ) : '' ;
4655 }
47- if (is_object ($ Data )) {
48- if (property_exists ($ Data , $ Segment )) {
56+ if (\ is_object ($ Data )) {
57+ if (\ property_exists ($ Data , $ Segment )) {
4958 return $ this ->dataTraverse ($ Data ->$ Segment , $ Path , $ AllowNonScalar , $ AllowMethodCalls );
5059 }
51- if ($ AllowMethodCalls && method_exists ($ Data , $ Segment )) {
60+ if ($ AllowMethodCalls && \ method_exists ($ Data , $ Segment )) {
5261 $ Working = $ Data ->{$ Segment }(...$ Path );
5362 return $ this ->dataTraverse ($ Working , [], $ AllowNonScalar );
5463 }
5564 }
56- if (is_string ($ Data )) {
57- if (preg_match ('~^(?:trim|str(?:tolower|toupper|len)) \\( \\)~i ' , $ Segment )) {
58- $ Segment = substr ($ Segment , 0 , -2 );
59- $ Data = $ Segment ($ Data );
60- }
65+ if (
66+ (\is_string ($ Data ) && \preg_match ('~^(?:str(?:tolower|toupper|len)|trim) \\( \\)$~i ' , $ Segment )) ||
67+ (\is_numeric ($ Data ) && \preg_match ('~^(?:floor|ceil) \\( \\)$~i ' , $ Segment ))
68+ ) {
69+ $ Segment = \substr ($ Segment , 0 , -2 );
70+ $ Working = $ Segment ($ Data );
71+ return $ this ->dataTraverse ($ Working , $ Path , $ AllowNonScalar , $ AllowMethodCalls );
6172 }
6273 return $ this ->dataTraverse ($ Data , $ Path , $ AllowNonScalar , $ AllowMethodCalls );
6374 }
75+
76+ /**
77+ * Used to redact sensitive properties from an object's dump.
78+ *
79+ * @return array An object's dumped properties.
80+ */
81+ public function __debugInfo (): array
82+ {
83+ $ Properties = \get_object_vars ($ this );
84+
85+ /** Attributes available as of PHP >= 8. Properties returned as is for older PHP versions. */
86+ if (!\class_exists ('\ReflectionProperty ' ) || !\method_exists ('\ReflectionProperty ' , 'getAttributes ' )) {
87+ return $ Properties ;
88+ }
89+
90+ foreach ($ Properties as $ Property => &$ Value ) {
91+ $ Reflection = new \ReflectionProperty ($ this , $ Property );
92+ $ Attributes = $ Reflection ->getAttributes ();
93+ foreach ($ Attributes as $ Attribute ) {
94+ $ Name = $ Attribute ->getName ();
95+ if ($ Name === 'Maikuolan\Common\Context ' ) {
96+ $ Arguments = $ Attribute ->getArguments ();
97+ if (!empty ($ Arguments ['Sensitive ' ])) {
98+ $ Value = $ Attribute ->newInstance ();
99+ }
100+ }
101+ }
102+ }
103+ return $ Properties ;
104+ }
64105}
0 commit comments